前提
在应用子组件时,是不可以包着其他内容的 🌰:
<father>
<child></child>
</father>
但是,有时需要自定义一些标签,或者添加一些内容。就形成了插槽
插槽的定义
slot(插槽):是组件的一块HTML模板,接受父组件传过来的插槽内容,生成Vnode并返回的函数。
插槽的分类
匿名插槽也叫单个插槽或默认插槽。不需要设置name属性,它隐藏的name属性是default
<!-- 封装的组件 child组件 -->
<template>
<div class="child>
<h1>子组件:匿名插槽</h1>
<slot></slot>
</div>
</template>
<!-- 组件调用页面 -->
<template>
<div class="parent">
<child>
<template>
<p>插入匿名插槽</p>
</template>
<child>
</div>
</template>
具名插槽需要设置name属性
<!-- 封装的组件 child组件 -->
<template>
<div class="child">
<h1>子组件:具名插槽</h1>
<slot name="child"></slot>
</div>
</template>
<!-- 组件调用页面 -->
<template>
<div class="parent">
<child>
<template v-slot:child>//另外一种写法:<template #child>
<p>插入具名插槽</p>
</template>
<child>
</div>
</template>
作用域插槽封装的组件要给插入的组件传值
<!-- 封装的组件 -->
<template>
<div class="child">
<h3>child组件标题</h3>
<slot :data="list"></slot>
</div>
</template>
data(){
return {
list:[1,2,3,4,5]
}
}
<!-- 组件调用页面-->
<template>
<div class="parent">
<child>
<template slot-scope="childData"> // vue2中的写法
<template v-slot="childData"> // vue2中的写法
<div v-for="(item,index) in childData.data">
{{item}}
</div>
</template>
<child>
</div>
</template>
跨组件传递slot
- 第一种:嵌套传递
- 第二种:Render函数,通过
$slots访问当前组件的slot元素,实现传递
vue2、vue3的区别
具名插槽
// vue3的写法
<div>
<Child>
<template v-slot:title>
<p>title的插槽</p>
</template>
</Child>
</div>
// Child组件
<div>
<p>
<slot name="title"></slot>
</p>
</div>
// vue2的写法
<div>
<Child>
<p slot="title">title的插槽</p>
</Child>
</div>
// Child组件
<div>
<p>
<slot name="title"></slot>
</p>
</div>
区别:
- vue3在父组件使用具名插槽时用的是v-slot,vue2使用slot
- vu3必须把v-slot写在template标签中,而vue2中slot可以写在任意标签中
作用域插槽
// vue3的写法
<div>
<Child>
<template v-slot:title="{data}">
<p>title的插槽:{{data}}</p>
</template>
</Child>
</div>
// Child组件
<div>
<p>
<slot name="title" :data="title"></slot>
</p>
</div>
// vue2的写法
<div>
<Child>
<p slot="title" slot-scope="scope">title的插槽{{scope.data}}</p>
</Child>
</div>
// Child组件
<div>
<p>
<slot name="title" :data="title"></slot>
</p>
</div>
data(){
return{
title:'组件的值'
}
}
区别:
- vue3在父组件获取值直接用v-slot,vue2中则使用slot-scope
slot原理
组件渲染原理
组件的核心是:渲染函数,组件的挂载本质是执行渲染函数并得到要渲染的VNode。 组件渲染的流程是先创建组件实例,然后初始化组件实例,在初始化组件实例的时候会处理slot相关的内容
slot初始化原理
- 源码的runtime-core\src\component.ts里
export function setupComponent(){
....
initslots(instance,children)
....
}
- 源码的runtime-core\src\componentSlots.ts里
// initSlots函数就是把children赋值给instance.slots
export const initSlots = ()=>{
}
vue2中slot与vue3之间的区别
vue2
父组件更新时,插槽会被重新渲染
vue3
- 当slot的内容发生变化时,只有子组件会被重新渲染
- 当父组件重新渲染时,如果子组件的内容未发生变动,子组件就不需要重新渲染