最近详细的看了vue插槽的文档,系统学习下来感觉vue3对于插槽的使用变化不是很大,以下为学习过程:
插槽注意点:
- v-slot只能添加在<templete>标签上面,如果只有一个默认插槽,组件的标签才可以被当做插槽的模板来使用。
- 父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子作用域中编译的。
- 为插槽设置后备内容(也就是在没有提供插槽内容的时候默认显示后备内容),实现如下:
MyButton.vue
<button>
<slot>Submit</slot>
</button>
Parent.vue
<my-button>Save</my-button> 插槽内容不为空时,渲染出来的代码为:
<button>Save</button>
<my-button></my-button> 插槽内容为空时,渲染出来的代码为:
<button>Submit</button>, 默认显示后备内容
- 具名插槽:
有时候需要多个插槽,可以给slot添加name属性来实现,没有name值时,默认为name值为default
再向具名插槽提供内容时,可以在<templete>元素上面使用v-slot指令,并以v-slot的参数的形式提供名称
缩写为:v-slot替换为#, 比如 v-slot:header 可以被重写为 #heade
Child.vue
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
Parent.vue
<child>
<templete v-slot:header>
this is a header!
</templete>
<template v-slot:default>
this is a content!
</template>
<template v-slot:footer>
this is a footer!
</template>
</child>
5. 作用域插槽:
父组件是不能直接访问子组件插槽中的数据,比如子组件渲染列表,自定义每个数据的渲染方式
// TodoList.vue: 子组件遍历循环渲染列表
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
// Parent.vue: 直接获取item是获取不到的,因为只有TodoList可以访问item
<child>
<span>{{item}}</span>
</child>
/* 为了解决这个问题,可以从父组件提供槽内容。要让item可用于父级提供的slot内容,可以添加slot元素并将其绑定为属性,如下:*/
TodoList.vue
<ul>
<li v-for="item in list">
<slot :item="item"></slot>
</li>
</ul>
/* Parent.vue: slotProps包含所有插槽props,这个名称有人可以自定义。绑定在<slot></slot>元素上的属性被称为插槽prop。现在我们就可以使用带有v-slot来定义我们提供的插槽prop的名字。*/
<todo-list>
<templete v-slot:default="slotProps">
<span>{{slotProps.item}}</span>
</templete>
</todo-list>
6. 解构插槽Prop:
作用域插槽的内部工作原理是将插槽内容包括在一个传入单个参数的函数里(其实v-slot中的值可以是任何能够作为函数定义中的参数的js表达式)。也可以使用解构来传入具体的插槽prop。
function (slotProps) {
// 插槽内容
}
Parent.vue:
<todo-list v-slot="{item}">
<templete>
<span>{{item}}</span>
</templete>
</todo-list>
// 这样模板看着更简洁,特别是提供多个prop的时候,还可以重命名/定义后背内容。
Parent.vue:
// 重命名prop
<todo-list v-slot="{item: todo}">
<templete>
<span>{{todo}}</span>
</templete>
</todo-list>
// 定义后备内容,用于处理prop为undefined的情况
<todo-list v-slot="{item='hello slot!'}">
<templete>
<span>{{item}}</span>
</templete>
</todo-list>
以上纯属个人学习观点,有问题欢迎指教~~