当前位置: 首页 > Web前端 > HTML

「Vue源码学习」你真的知道插槽Slot是怎么“插”的吗

时间:2023-03-29 12:52:54 HTML

《Vue源码学习》你真的知道插槽是怎么“插”的吗?导出,这是它在Vue文档中所说的。具体来说,插槽是一个“空间”,允许您在组件中添加内容。你真的知道插槽是如何“插入”的吗?希望你能像我一样,诚实、简单地阅读这篇文章。vueslotslot的基本使用是单槽|匿名槽//子组件:(假设命名为:child)//父组件:(引用子组件child)我们知道如果在中添加内容“林三鑫”,文本“林三鑫”就会不会呈现在页面上。那么我们如何让添加的内容可显示呢?只需在子组件中添加一个插槽即可。//子组件:(假设名称:child)编译作用域(父组件在子组件Insertdata)上面我们了解到,slot其实就是一个‘空间’,可以让我们在父组件中给子组件添加内容。我们可以在父组件中添加任意数据值,比如这样://父组件:(引用子组件child)newVue({el:'.app',data:{parent:'parentcomponent'}})usingdata的语法完全没变,但是我们是不是可以直接在子组件??很明显不是!!//子组件:(假设名称:child)newVue({el:'child',data:{child:'childcomponent'}})//父组件:(引用子组件child)不允许将数据直接传递到子组件中。因为:父模板中的所有内容都是在父范围内编译的;子模板中的所有内容都在子范围内编译。备份内容(子组件设置默认值)所谓备份内容,其实就是slot的默认值。有时候我没有在父组件中添加内容,那么slot会显示默认值,比如://子组件:(Assumedname:child)命名槽(多个子组件对应插入的内容)有时候,子组件中可能有多个槽,那么我们如何将父组件中的相应内容精确地插入到想要的位置?给slot起个名字就可以了,也就是加上name属性。//子组件:(假定名称:child)父组件传递,或者slot="name"(旧语法),v-slot:nameor#name(新语法)添加内容://父组件:(引用子组件child)这是插入到第二个槽位的内容这是插入到第三slot的内容

scopeslot(父组件在子组件使用子组件数据)通过slot我们可以使用父组件向子组件添加内容。通过命名插槽,我们可以在多个位置添加内容。但是我们添加的数据是在父组件中的。上面我们说了子组件中的数据不能直接使用,但是我们有没有其他方法可以让我们使用子组件的数据呢?其实我们也可以使用slot-scope方法://Subcomponent:(Assumedname:child)newVue({el:'child',data:{child1:'data1',child2:'data2'}})//父组件:(引用子组件child){{slotde.value2}}//同上,由于子组件没有命名slot,所以默认值为default
Slotslot是如何“插入”的(大众版)普通slot//子组件:(假设命名为:child)//父组件:(引用子组件child)
newVue({el:'.app',data:{parent:'父组件的值'}})先解析父组件,子元素作为子元素处理,slot作为子元素处理child的元素,并在父组件作用域中获取parent变量的值,生成这样一个节点:{tag:"div",children:[{tag:"child",children:['这是父组件插入默认slot的值','这是内容的父组件插入一个slot的值']}]}子组件解析,slot作为占位符,会被解析成一个函数,大致意思如下{tag:"div",children:['I'minthechildcomponent',_t('default'),//匿名slot,默认名称为default_t('one')//命名slot,名称为one]}_t函数需要传递输入插槽名称,默认为default,name传入命名插槽。这个函数的作用是获取第一步解析出的slot节点,然后返回解析出的节点,那么子组件的节点就完整了,slot也成功认父了——divtag{tag:"div",children:['我在子组件中','这是父组件插入默认槽的值','这是内容父组件插入一个槽的值']}scoped插入Slot//子组件:(假设名称:child)newVue({el:'child',data:{child1:'子数据1',child2:'子数据2'}})//父组件:(引用子组件child)插入一个slot{{slotone.value1}}{{slotone.value2}}
过程很复杂,这里说个通俗点,先解析父组件,遇到scopeslot时,会把这个slot封装成一个函数保存在子元素child{tag:"div",children:[{tag:"child"scopeSlots:{default(data){//记住这个data参数return['插入到一个slot中,插入到defaults中很多'+数据.value1+data.value2]},one(data){//记住这个data参数return['insertintooneslot'+data.value1+data.value2]}}}]}2.轮到子了组件分析Now,这时候_t函数又出场了,子组件将对应的slot数据包装成一个对象,传入到_t函数中{tag:"div",children:['我在subcomponent',_t('default',{value1:'subdata1',value2:'subdata1'}),_t('one',{value1:'subdata2',value2:'subdata2'})]}接下来是内部执行_t,将打包后的对象作为数据参数传入scopeSlots中对应的函数,解析为:{tag:"div",children:['我在子组件中','插入默认槽中子数据1subdata1','insertoneslotneutrondata2subdata2']}$slots看到这里,相信大家已经明白大概的流程了(虽然不是很详细),那么还有一个问题呢解析节点VNode对象存在吗?你不能把它解析出来然后扔掉,对吧?你必须找到一个地方保存它,然后渲染真正的dom。这个地方是$slots//subcomponent:(Assumedname:child)newVue({el:'.child',created(){控制台.log(this.$slots)//看看里面有什么}})//父组件:(引用子组件child)这是插入到twoslot的内容template>这是插入三槽的内容console.log的结果:看到这里大家明白了$slots是一个Map,key是每个slot的名字(默认是匿名slot的key),key对应的value是每个slot下的VNode节点。具体的VNode对象长什么样子?,大家可以自己输出,里面的东西太多了,这里就不展示了嘿嘿。结语我是林三鑫,一个狂热的前端菜鸟程序员。如果你有上进心,喜欢前端,想学前端,那我们可以交个朋友,一起钓鱼哈哈,摸摸鱼群,加我,请注意[思想]

猜你喜欢