写文章不容易,点个赞呗兄弟
专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】
如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧
【Vue原理】Slot - 白话版
插槽作为组件一个重要的部分,在项目中也是经常会用到的,起到自定义组件的作用。
插槽,按照处理方式,我觉得大概可以分为两种,一种是普通插槽,一种是作用域插槽
普通插槽,就是不给名字的默认插槽和 具名插槽
作用域插槽,就是使用子作用域数据的插槽
接下来,我们简单解释一下插槽的处理流程,主要理解思想和流程
普通插槽
下面以默认插槽来说,就是不给名字的插槽
父组件中使用组件 test,并且使用插槽
子组件 test 模板
1、父组件先解析,把 test 当做子元素处理,把 插槽当做 test 的子元素处理,生成这样的节点
{ tag: "div", children: [{ tag: "test", children: ['插入slot 中'] }]}
插槽的节点就是上面的
['插入slot 中']
2、子组件解析,slot 作为一个占位符,会被解析成一个函数
大概意思像 解析成下面
{ tag: "main", children: [ '我在子组件里面', _t('default') ]}
3、这个 _t 函数,传入 'default ' 参数并执行
因为这里不给名字,默认插槽,所以是default,如果给了名字,就传入你的名字
这个函数的作用,是把第一步解析得到的插槽节点拿到,然后返回
那么子组件的节点就完整了,插槽也成功认了爹
{ tag: "main", children: ['我在子组件里面','插入slot 中']}
作用域插槽
父组件中使用 test 组件,test 组件使用作用域插槽
子组件 test 模板
子组件的数据
1、父组件先解析,把 test 当做子元素处理,把 插槽包装成一个函数,保存给节点
大概意思是这样,为了便于理解主要思想,实际操作要复杂很多
{ tag: "div", children: [{ tag: "test" scopeSlots:{ default(slotProps){ return ['插入slot 中' + slotProps] } } }]}
2、子组件解析,slot 作为一个占位符,会被解析成一个函数
{ tag: "main", children: [ '我在子组件里面', _t('default',{child:11}) ]}
这个 _t 函数,和普通插槽 的一样,但是你可以看到,多传了一个参数 { child:11 }
为什么多一个参数?因为这是作用域插槽啊,子组件要传给插槽的数据啊
_t 函数执行的时候,得到两个参数
1、插槽函数名字 default
2、需要的作用域数据 { child:11 }
_t 内部执行
1、根据传入的名字('default'),拿到第一步解析插槽得到的函数(代号为A)
2、执行A,传入参数 { child:11 }
function A(slotProps){ return ['插入slot 中' + slotProps]}
于是作用域插槽,就拿到了子组件传过来的数据了
插槽函数执行,会返回解析后的插槽节点,_t 拿到这个节点,直接 return 出去
于是子组件插槽就完成替换 slot 占位符了,变成下面这样
{ tag: "main", children: [ '我在子组件里面', _t('default',{child:11}) ]}变成下面这样{ tag: "main", children: [ '我在子组件里面', '插入slot 中 {child:11}' ]}