简单看一下普通插槽slot
2021-03-23 本文已影响0人
HelenYin
先看普通插槽
这里我仍然不看编译,直接用render函数来写slot,用下面这个例子
// 子组件
const AppLayout = {
render(h) {
return h('div', {}, [
h('header', {}, [this.$slots.header]),
h('main', {}, [this.$slots.default]),
h('footer', {}, [this.$slots.footer]),
]);
}
};
// 父组件
new Vue({
el: '#app',
data() {
return {
title: '我是标题',
msg: '我是内容',
desc: '其它信息'
}
},
render(h) {
return h('div', {}, [
h(AppLayout, {}, [
h('h1', { slot: 'header' }, this.title),
h('p', { slot: 'default' }, this.msg),
h('p', { slot: 'footer' }, this.desc),
])
]);
},
});
首先我直接执行肯定会报错,因为到目前为止我还没有实现this.$slots
。那么这里需要实现的就是把slot赋值给this.$slots
。
首先需要知道,slot本质上就是vnode,this.$slot
存储的就是vnode。
这里我仍然把用户写的slot,放在Component 的 children中。我们在子组件实例化的时候,遍历children,如果child的data中有slot属性,就把它赋值给$slot
。那么父组件里把子组件的vnode引用一下,在initInternalComponent
函数里来做。parentVnode.componentOptions.children
就是。
在initInternalComponent里做了这个赋值之后,接下来在initRender里来把$slots
搞定一下。
export function initRender (vm) {
+ if (vm.$options._renderChildren) {
+ vm.$slots = resolveSlots(vm.$options._renderChildren, vm);
+ }
vm.$createElement = (tag, data, children) => createElement(tag, data, children, vm);
}
function resolveSlots (chidren, vm) {
const slot = {};
for (const child of chidren) {
if (child.data.slot) {
slot[child.data.slot] = [child];
}
}
return slot;
}
代码实现还是在这个仓库
https://github.com/TingYinHelen/tempo