#vue.js #vuejs3 #vue-composition-api #slots
Вопрос:
МАКВЕ
https://github.com/hyperbotauthor/minvue3cliapp
MCVE в прямом эфире
https://codesandbox.io/s/white-browser-fl7ji
У меня есть приложение Vue 3 cli-сервис, которое использует компоненты API композиции со слотами.
HelloWorld
Компонент отображает слоты, которые он получает, в div
:
// src/components/Helloworld.js
import { defineComponent, h } from "vue";
export default defineComponent({
setup(props, { slots }) {
return () => h("div", {}, slots);
}
});
Composite
Компонент использует HelloWorld
в своей setup
функции и заполняет свои слоты:
// src/components/Composite.js
import { defineComponent, h } from "vue";
import HelloWorld from "./HelloWorld";
export default defineComponent({
setup(props, { slots }) {
return () =>
h(HelloWorld, {}, [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
}
});
Приложение использует оба способа визуализации одних и тех же двух дивов:
<template>
<!--<img alt="Vue logo" src="./assets/logo.png">-->
Works with plain slots
<HelloWorld>
<div>Div 1</div>
<div>Div 2</div>
</HelloWorld>
Triggers warning when slots are used from other component
<Composite> </Composite>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
import Composite from "./components/Composite";
export default {
name: "App",
components: {
HelloWorld,
Composite,
},
};
</script>
<style>
</style>
Composite
Компонент запускает это предупреждение:
Non-function value encountered for default slot. Prefer function slots for better performance.
То же самое предупреждение не срабатывает, когда я использую HelloWorld
только шаблон.
Я не понимаю, в чем разница, если я использую слоты из шаблона или из другого компонента.
В чем смысл этого предупреждения?
Есть ли какой-нибудь способ удалить это предупреждение?
Ответ №1:
Предупреждение касается массива VNode
s, созданного в setup()
функции визуализации «s Composite.js
«.
// src/components/Composite.js
export default defineComponent({
setup(props, { slots }) {
return () =>
h(HelloWorld, {}, [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
});
Это неэффективно, поскольку дочерний слот отображается еще до HelloWorld
того, как компонент сможет его использовать. Дочерний слот по существу отображается в родительском, а затем передается дочернему. Включение генерации дочернего слота в функцию откладывает выполнение работы до тех пор, пока дочерний элемент не будет отрисован.
Я не понимаю, в чем разница, если я использую слоты из шаблона или из другого компонента.
@vue/compiler-sfc
компилирует <template>
из SFCs в функцию визуализации, где слоты передаются как функции, что позволяет избежать предупреждения, которое вы наблюдали.
Решение
Вместо того, чтобы отображать дочерний слот в родительском (т. Е. Напрямую передавать массив VNodes
в качестве slots
аргумента), оберните его в функцию:
// src/components/Composite.js
export default defineComponent({
setup(props, { slots }) {
return () => 👇
h(HelloWorld, {}, () => [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
}
});
Обратите внимание, что внутренним h()
вызовам не нужна эта оболочка функции, потому что все они отображаются вместе со слотом по умолчанию.