简单看一下普通插槽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

上一篇 下一篇

猜你喜欢

热点阅读