Hello, everyone. I’m Lin Sanxin. Vue has implemented a set of content distribution APIs. The<slot>
element is used as an export for carrying and distributing content. This is the description on the Vue document. Specifically,slot
that allows you to add content in the component. Do you really know how the Slot is "inserted"? I hope you can be as innocent as I am and read this article honestly.
The basic use of Vue slot slot
Single slot | anonymous slot
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
</div>
</template>
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
林三心
</child>
</div>
</template>
We know that if the content "Lin Sanxin" is added directly to the <child></child> in the parent component, the text "Lin Sanxin" will not be rendered on the page. So how do we enable the added content to be displayed? Just add slot in the subcomponent.
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot></slot>
</div>
</template>
Compilation scope (the parent component inserts data <slot></slot>
As we learned above, a slot is actually a'space' that allows us to add content from the parent component to the child component. We can add any data value in the parent component, for example:
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child> {{ parent }}</child>
</div>
</template>
new Vue({
el:'.app',
data:{
parent:'父组件'
}
})
The syntax for using data has not changed at all, but can we directly use the data in the subcomponents? Obviously not! !
// 子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot></slot>
</div>
</template>
new Vue({
el:'child',
data:{
child:'子组件'
}
})
// 父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child> {{ child }}</child>
</div>
</template>
It is not possible to directly pass in the data in the sub-component. Because: all content in the parent template is compiled in the parent scope; all content in the child template is compiled in the child scope.
Fallback content (subcomponent <slot></slot>
set default value)
The so-called back content is actually the default value of the slot. Sometimes I do not add content in the parent component, then the slot will display the default value, such as:
//子组件 : (假设名为:child)
<template>
<div class='child'>
<slot>这就是默认值</slot>
</div>
</template>
Named slot (multiple sub-components <slot></slot>
correspond to the inserted content)
Sometimes, there may be more than one slot in the child component, so how do we insert the corresponding content in the parent component exactly where we want it? Just give the slot a name, that is, add the name attribute.
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot name='one'> 这就是默认值1</slot>
<slot name='two'> 这就是默认值2 </slot>
<slot name='three'> 这就是默认值3 </slot>
</div>
</template>
The parent component can add content slot="name" (old syntax), v-slot:name
or #name (new syntax):
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
<template v-slot:"one"> 这是插入到one插槽的内容 </template>
<template v-slot:"two"> 这是插入到two插槽的内容 </template>
<template v-slot:"three"> 这是插入到three插槽的内容 </template>
</child>
</div>
</template>
Scope slot (the parent component uses the child component data <slot></slot>
Throughslot
we can add content to the child component in the parent component, and byslot
, we can add content in more than one location. But the data we add is in the parent component. We said above that we cannot directly use the data in the sub-components, but do we have other ways to allow us to use the data in the sub-components? In fact, we can also useslot-scope
:
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot name= 'one' :value1='child1'> 这就是默认值1</slot> //绑定child1的数据
<slot :value2='child2'> 这就是默认值2 </slot> //绑定child2的数据,这里我没有命名slot
</div>
</template>
new Vue({
el:'child',
data:{
child1:'数据1',
child2:'数据2'
}
})
//父组件:(引用子组件 child)
<template>
<div class='app'>
<child>
<template v-slot:one='slotone'>
{{ slotone.value1 }} // 通过v-slot的语法 将子组件的value1值赋值给slotone
</template>
<template v-slot:default='slotde'>
{{ slotde.value2 }} // 同上,由于子组件没有给slot命名,默认值就为default
</template>
</child>
</div>
</template>
How is the Slot "plugged in" (popular version)
Normal slot
//子组件 : (假设名为:child)
<template>
<div class='child'>
我在子组件里面
<slot></slot>
<slot name="one"></slot>
</div>
</template>
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
这是插入到默认插槽的内容 {{parent}}
<template v-slot:"one"> 这是插入到one插槽的内容 {{parent}}</template>
</child>
</div>
</template>
new Vue({
el:'.app',
data:{
parent:'父组件的值'
}
})
The parent component parses first, treats
child
as a child element, treats the slot aschild
, and obtains the value of the parent variable in the scope of the parent component, and generates such a node:{ tag: "div", children: [{ tag: "child", children: ['这是插入到默认插槽的内容 父组件的值', '这是插入到one插槽的内容 父组件的值'] }] }
Sub-component analysis,
slot
as a placeholder, will be parsed into a function, probably meaning like the following{ tag: "div", children: [ '我在子组件里面', _t('default'), // 匿名插槽,默认名称为default _t('one') // 具名插槽,名称为one ] }
The _t function needs to pass in the slot name, the default is
default
, and the named slot is passed inname
. The function of this function is to get the slot node obtained by the first analysis, and then return the resolved node, then the subcomponent The node is complete, and the slot has successfully recognized the daddy-div
label{ tag: "div", children: ['我在子组件里面', '这是插入到默认插槽的内容 父组件的值', '这是插入到one插槽的内容 父组件的值'] }
Scope slot
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot :value1='child1' :value2='child1'></slot>
<slot name='one' :value1='child2' :value2='child2'></slot>
</div>
</template>
new Vue({
el:'child',
data:{
child1: '子数据1',
child2: '子数据2'
}
})
//父组件:(引用子组件 child)
<template>
<div class='app'>
<child>
<template v-slot:default='slotde'>
插入默认 slot 中{{ slotde.value1 }}{{ slotde.value2 }}
</template>
<template v-slot:one='slotone'>
插入one slot 中{{ slotone.value1 }}{{ slotone.value2 }}
</template>
</child>
</div>
</template>
child
. The parent component is parsed first, and when it encounters a scope slot, it will encapsulate this slot into a function and save it under the child element 061ca76b40ba9d{ tag: "div", children: [{ tag: "child" scopeSlots:{ default (data) { // 记住这个data参数 return ['插入one slot 中插入默认 slot 中' + data.value1 + data.value2] }, one (data) { // 记住这个data参数 return ['插入one slot 中' + data.value1 + data.value2] } } }] }
2. It is the turn of the sub-component to analyze, this time the _t function is on the scene again, and the sub-component wraps the corresponding slot data into an object and passes it into the _t function
{
tag: "div",
children: [
'我在子组件里面',
_t('default',{value1: '子数据1', value2: '子数据1'}),
_t('one',{value1: '子数据2', value2: '子数据2'})
]
}
The next step is the internal execution of _t. The wrapped object is passed as the data parameter to the corresponding functions in scopeSlots and parsed into:
{
tag: "div",
children: [
'我在子组件里面',
'插入默认 slot 中 子数据1 子数据1',
'插入one slot 中 子数据2 子数据2'
]
}
$slots
Seeing this, I believe that everyone has already understood about the process (although it is not very detailed), then there is another question. node VNode objects exist? You can't parse it out and throw it away, right? You must find a place to save it and perform the rendering of the real dom $slots
//子组件 : (假设名为:child)
<template>
<div class= 'child'>
<slot></slot>
<slot name='one'></slot>
<slot name='two'></slot>
<slot name='three'></slot>
</div>
</template>
new Vue({
el:'.child',
created () {
console.log(this.$slots) // 看看里面有啥
}
})
//父组件:(引用子组件 child)
<template>
<div class= 'app'>
<child>
<template> 这是插入到默认插槽的内容 </template>
<template v-slot:"one"> 这是插入到one插槽的内容 </template>
<template v-slot:"two"> 这是插入到two插槽的内容 </template>
<template v-slot:"three"> 这是插入到three插槽的内容 </template>
</child>
</div>
</template>
The result of console.log:
Seeing that everyone understands here,$slots
is aMap
,key
is the name of each slot (key
fordefault
), the value corresponding to the key is the VNode node under each slot, and the specific VNode object is all You can output it yourself to see what it looks like. There are too many things in it, so I won't show it here. Hey-hey.
Concluding remarks
I am Lin Sanxin, an enthusiastic front-end rookie programmer. If you are motivated, like the front-end, and want to learn the front-end, then we can make friends, fish together haha, fish school, add me, please note [think]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。