vue.js - “默认插槽遇到非函数值。” 在 Vue 3 组合 API 组件中
问题描述
MCVE
https://github.com/hyperbotauthor/minvue3cliapp
MCVE 直播
https://codesandbox.io/s/white-browser-fl7ji
我有一个 Vue 3 cli-service 应用程序,它使用带有插槽的组合 API 组件。
该HelloWorld
组件在 a 中呈现它接收到的插槽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"])]);
}
});
该应用程序使用两种方式来呈现相同的两个 div:
<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
仅使用模板时,不会触发相同的警告。
如果我使用模板或其他组件中的插槽,我不明白有什么区别。
这个警告有什么意义?
有什么办法可以消除这个警告吗?
解决方案
警告是关于在中的渲染函数中VNode
创建的 s数组。setup()
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
将 from SFC编译<template>
为渲染函数,其中插槽作为函数传递,从而避免了您观察到的警告。
解决方案
与其在父级中渲染子槽(即,直接传递一个数组VNodes
作为slots
参数),不如将其包装在一个函数中:
// src/components/Composite.js
export default defineComponent({
setup(props, { slots }) {
return () =>
h(HelloWorld, {}, () => [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
}
});
请注意,内部h()
调用不需要此函数包装器,因为它们都由 child与默认插槽一起呈现。
推荐阅读
- r - 来自 httr POST-request 的数据是长字符串而不是表
- reactjs - Keycloak & React Router 路由用于公共/登录 & Authenticated & 基于角色的路由
- windows - 在新的 Azure VM 上通过 PS-Session 访问 Windows.Security.Credentials.PasswordVault
- android-recyclerview - 如何在 RecyclerView 中保存用户输入
- java - 如何解析来自 CNBC 市场页面的表格数据?
- python - ImportError:无法从“kivy.lib”导入名称“osc”
- c# - 尝试序列化对象列表时,Xml 序列化输出一个空对象
- git - 有没有一种简单的方法可以在 git 上退出这种情况?
- api - 使用 IHttpContextAccessor 调用 API 服务时的单元测试异常
- linux - 如何结合if语句和linux命令排序?