vue 里提供了一种将父组件的内容和子组件的模板整合的方法: 内容分发, 通过 slot 插槽来实现.
在组件标签内部写入的内容默认的会被替换掉, 如果想要在组件的模板里使用这些内容, 就在对应的位置写上 slot 标签, 这个 slot 标签就代表着这些内容.
匿名槽口
在父组件中使用子组件的时候, 在子组件标签内部写的内容, 在子组件的模板中可以通过 < slot></slot > 来使用
- <div id = "app">
- <aaa>
- <h3>slot 槽口插入的内容 </h3>
- </aaa>
- </div>
- <template id="aaa">
- <div class = "aaa">
- <slot></slot>
- <p > 我是 aaa 组件 </p>
- </div>
- </template>
image
具名槽口
父组件在子组件标签内写的多个内容我们可以给其设置 slot 属性来命名, 在子组件的模板通过使用带有 name 属性的 slot 标签来放置对应的 slot, 当 slot 不存在的时候, slot 标签内写的内容就出现.
slot 上面通过 name 属性指定槽口名称, 然后使用的时候通过 slot="槽口名称".
- <div id = "app">
- <aaa>
- <!-- <h3>slot 槽口插入的内容 </h3> -->
- <p slot = "s1"> 在上面的内容 </p>
- <p slot = "s2"> 在下面的内容 </p>
- </aaa>
- </div>
- <template id="aaa">
- <div class = "aaa">
- <slot name = "s1"></slot>
- <p > 我是 aaa 组件 </p>
- <slot name = "s2"></slot>
- </div>
- </template>
image
slot 插槽让我们在原有模版的基础上, 定制更加多样化的组件.
作用域插槽
当我们想在父组件中访问子组件内部的一些数据时, 就需要在子组件内部的 < slot > 元素上动态绑定一个自定义属性, 将数据传递到自定义属性上, 通过 slot 传递给父组件使用.
<slot :teacher="teacher"></slot>
绑定到 < slot > 元素上的属性我们称之为 slot props. 现在, 在父组件中我们可以通过 slot-scope 给包含所有插槽 prop 的对象命名为 prop, 之后就可以通过 prop 来使用子组件中的数据了.
<template slot-scope="prop">
老师姓名:{{prop.teacher.name}} 老师年龄:{{prop.teacher.age}}
</template>
image
v-slot
v-slot 指令自 Vue 2.6.0 起被引入, 提供更好的支持 slot 和 slot-scope 特性的 API 替代方案. 在接下来所有的 2.x 版本中 slot 和 slot-scope 特性仍会被支持, 但已经被官方废弃, 且不会出现在 Vue 3 中.
现在我们使用 v-slot 重构上面的代码:
<template v-slot:default="prop">
老师姓名:{{prop.teacher.name}} 老师年龄:{{prop.teacher.age}}
</template>
一个不带 name 的 <slot> 出口会带有隐含的名字 "default", 使用时可以简化为 v-slot="prop".
具名槽口
子组件中通过 name 属性给槽口设定名称
<slot name="student" :student='student'></slot>
父组件中通过 v-slot: 名称的方式来使用具名槽口
<template v-slot:student="prop">
学生姓名:{{prop.student.name}} 学生年龄:{{prop.student.age}}
</template>
当我们在父组件中多次调用子组件时, 可以通过设置不同的样式, 来设定子组件中数据的展示形式.
父子组件通信案例
通过属性绑定和 v-slot 我们也可以在子组件中循环渲染父组件中的数据
首先我们在父组件中定义一组数据
- data(){
- return{
- listData:[
- {
- name:"Tome",
- job:"web 前端"
- },
- {
- name:"Lily",
- job:"java"
- }
- ]
- }
- }
将数据通过属性绑定的方式传递给子组件 Home, 并且设定一个 v-slot 插槽对象名称, 这时候插槽内部就可以通过 prop 来访问数据
<Home :data = "listData" v-slot = "prop">
在 Home 组件中接收父组件传递过来的 data
- props:{
- data:{
- type:Array,
- required:true
- }
- }
将 data 传递到 slot 的自定义属性 list 中
- <template>
- <div class="home">
- <slot :list = "data"></slot>
- </div>
- </template>
将 Child 组件插到 Home 组件的 slot 槽口中, 并且 Child 组件可以通过 prop.list 来循环渲染数据, 并且将 item 通过属性绑定的方式传递给 Child
<Child v-for = "(item,index) in prop.list" :key = index :data = "item"></Child>
在 Child 组件中接收 Home 传递过来的 data
- props:{
- data:{
- type:Object,
- required:true
- }
- }
并且在页面中通过 key 名来渲染数据
- <div class="home">
- <p>{{data.name}}</p>
- <p>{{data.job}}</p>
- </div>
渲染结果:
image
来源: http://www.jianshu.com/p/74e4f8e6b3d5