Vue Slots Through a Function Lens
Reinterpreting Vue's default, named, and scoped slots as function calls to build a clearer mental model.
用另一种方式来理解 slot 的本质——把它当成函数调用。
子组件(comp)有这样的格式:
1
2
3
4
5
6
7
8
9
//comp.vue
<template>
<div>
<slot></slot>
<slot name="slot1"></slot>
<slot name="slot2" msg="hello"></slot>
</div>
</template>
在父组件使用的时候,按照对应的标识,传入标签。
1
2
3
4
5
6
7
8
9
10
11
12
13
//index.vue
<Comp>
<p>默认插槽</p>
<template #slot1>
<p>具名插槽</p>
</template>
<template #slot2="{ msg }">
<p>作用域插槽:</p>
</template>
</Comp>
在父组件使用 comp 时,相当于传递了一个对象,三个属性,值均为函数:
1
2
3
4
5
{
default: function(){},
slot1: function(){},
slot2: function(){}
}
在 comp 内部调用对应的方法——<slot></slot> 等价于调 props.default()。说着说着感觉有点 React 的味道了。
用 JS 来实现 comp 组件:
1
2
3
4
5
6
7
8
9
10
//comp.js
import { createElementVNode } from "vue";
export default {
setup() {
return () => {
return createElementVNode("div", null, []); // 创建虚拟节点
};
},
};
拿到参数,
1
2
3
4
5
6
7
8
9
export default {
setup(props, ctx) {
//两个参数 第二个参数包含了一些其他信息
console.log("ctx", ctx);
return () => {
return createElementVNode("div", null, []); // 创建虚拟节点
};
},
};
执行对应的方法,
1
2
3
4
5
6
7
8
export default {
setup(props, { slots }) {
const defaultVNode = slots.default(); // 调用默认方法
return () => {
return createElementVNode("div", null, [...defaultVNode]);
};
},
};
因此,原先的 comp.vue 可以写成 comp.js,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//comp.js
import { createElementVNode } from "vue";
export default {
setup(props, { slots }) {
const defaultVnode = slots.default();
const slot1Vnode = slots.slot1();
const slot2Vnode = slots.slot2({
msg: "hello",
});
return () => {
return createElementVNode("div", null, [
...defaultVnode,
...slot1Vnode,
...slot2Vnode,
]);
};
},
};
This post is licensed under CC BY 4.0 by the author.