Vue插槽(Slots)用于向组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。插槽也是属于一种父组件到子组件的组件间通行的方式。
Vue插槽有以下3种类型:
- 默认插槽。
- 具名插槽。
- 作用域插槽。
默认插槽
使用默认插槽时,只需在子组件模板中,将要从外部传入的模板内容,使用<slot>进行占位即可。
例如有一个名为display-frame的组件,其模板内容如下:
1<div class="display-frame">
2 <h3>{{title}}</h3>
3 <!-- 默认插槽,等待组件的使用者进行填充 -->
4 <slot>
5 默认插槽内容。使用者没有传递结构时,会显示。
6 </slot>
7</div>
该组件的使用方式如下:
1<display-frame title="用户信息">
2 <!--
3 在组件标签体中的内容,
4 会被插入到组件中使用了 <slot> 的位置
5 -->
6 <ul>
7 <li>姓名:{{ user.name }}</li>
8 <li>性别:{{ user.sex }}</li>
9 <li>年龄:{{ user.age }}</li>
10 </ul>
11</display-frame>
注:插槽在使用过程中,
<slot>标签并不限制使用次数,意味着可以在模板中显示两个相同的插槽内容。并且,在使用标签内容插入模板时,标签内容并不需要像组件模板一样需要在外部有一个作为根的元素。
具名插槽
具名插槽就是指给组件插槽位置指定一个名称。外部在使用组件标签时,可以通过插槽名称指定模板要插入到组件中的位置。
定义插槽名称使用的是<slot>标签的name属性:
1<div class="display-frame">
2 <slot name="header">
3 <div>Header</div>
4 </slot>
5 <slot name="main">
6 <div>Main</div>
7 </slot>
8 <slot name="footer">
9 <div>Footer</div>
10 </slot>
11</div>
上方定义了3个插槽,分别是header、main和footer。使用方式有两种:
-
slot属性:1slot="slot-name"1<display-frame> 2 <h3 slot="header">{{ title }}</h3> 3 <img slot="main" src="https://blog.linner.asia/images/avatar.jpg"> 4 <ul slot="main"> 5 <li>姓名:{{ user.name }}</li> 6 <li>性别:{{ user.sex }}</li> 7 <li>年龄:{{ user.age }}</li> 8 </ul> 9 <template slot="footer"> 10 <a href="https://blog.linner.asia">博客主页</a> 11 <a href="https://blog.linner.asia/about/">个人信息</a> 12 <a href="https://blog.linner.asia/contact/">联系用户</a> 13 </template> 14</display-frame>slot属性可以作用在普通元素标签上,也可以作用在<template>上。并且同个插槽可以同时存放多个元素(模板),只需要定义多个具有相同的slot属性的元素,或者使用<template>将它们包裹起来即可。 -
v-slot指令:1v-slot:slot-name1<display-frame> 2 <template v-slot:header> 3 <h3 slot="header">{{ title }}</h3> 4 </template> 5 <template v-slot:main> 6 <img src="https://blog.linner.asia/images/avatar.jpg"> 7 <ul> 8 <li>姓名:{{ user.name }}</li> 9 <li>性别:{{ user.sex }}</li> 10 <li>年龄:{{ user.age }}</li> 11 </ul> 12 </template> 13 <template v-slot:footer> 14 <a href="https://blog.linner.asia">博客主页</a> 15 <a href="https://blog.linner.asia/about/">个人信息</a> 16 <a href="https://blog.linner.asia/contact/">联系用户</a> 17 </template> 18</display-frame>v-slot指令在使用时,只能在<template>上使用,不能在其它元素标签上使用。
默认插槽就是没有提供
name的<slot>。没有提供name的<slot>出口会隐式地命名为default。
渲染作用域
插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的。例如:
1<span>{{ message }}</span>
2<display-frame>{{ message }}</display-frame>
两个标签中的{{ message }}插值表达式渲染的内容都是一样的。
需要注意的是,插槽的内容无法访问子组件的数据(无法直接访问)。因为Vue模板中的表达式只能访问其定义时所处的作用域,这和JavaScript的词法作用域规则是一致的。
也就是说,在哪个文件中定义的模板,其数据的作用域就在哪个文件,其表达式访问的也是该文件中的数据。
作用域插槽
作用域插槽可以让组件在定义插槽位置时,将组件中的一些数据,通过插槽<slot>,像props传递数据那样,将数据传递给父组件使用。
向父组件传递数据:
1<template>
2<div class="user-info">
3 <slot :username="name" :age="18" :sex="男">
4</div>
5</template>
6
7<script>
8export default {
9 name: 'user-info',
10 data() {
11 name: '张三',
12 age: 18,
13 sex: '男',
14 },
15}
16</script>
父组件接收数据,并为子组件定义插槽模板,有3种方式:
-
scope:1<user-info> 2 <template scope="userInfo"> 3 <ul> 4 <li>姓名:{{userInfo.username}}</li> 5 <li>性别:{{userInfo.sex}}</li> 6 <li>年龄:{{userInfo.age}}</li> 7 </ul> 8 </template> 9</user-info> -
slot-scope:1<user-info> 2 <template slot-scope="userInfo"> 3 <ol> 4 <li>姓名:{{userInfo.username}}</li> 5 <li>性别:{{userInfo.sex}}</li> 6 <li>年龄:{{userInfo.age}}</li> 7 </ol> 8 </template> 9</user-info> -
v-slot:1<user-info> 2 <template v-slot="userInfo"> 3 <h3>姓名:{{userInfo.username}}</h3> 4 <h3>性别:{{userInfo.sex}}</h3> 5 <h3>年龄:{{userInfo.age}}</h3> 6 </template> 7</user-info>与前两种不同的是,
v-slot可以指定插槽位置:1<template> 2<div class="user-info"> 3 <slot name="main" :username="name" :age="18" :sex="男"> 4</div> 5</template>1<user-info> 2 <template v-slot:main="userInfo"> 3 <ul> 4 <li>姓名:{{userInfo.username}}</li> 5 <li>性别:{{userInfo.sex}}</li> 6 <li>年龄:{{userInfo.age}}</li> 7 </ul> 8 </template> 9</user-info>scope和slot-scope指定卡槽需要配合slot属性。v-slot可以直接在组件标签上使用:1<user-info v-slot="userInfo"> 2 <ol> 3 <li>姓名:{{userInfo.username}}</li> 4 <li>性别:{{userInfo.sex}}</li> 5 <li>年龄:{{userInfo.age}}</li> 6 </ol> 7</user-info>
这3种使用方式都支持解构赋值:
1<user-info>
2 <template slot-scope="{username, sex, age}">
3 <h2>姓名:{{username}}</h2>
4 <h4>性别:{{sex}}</h4>
5 <h4>年龄:{{age}}</h4>
6 </template>
7</user-info>
8
9<user-info v-slot="{username, sex, age}">
10 <h2>姓名:{{username}}</h2>
11 <h4>性别:{{sex}}</h4>
12 <h4>年龄:{{age}}</h4>
13</user-info>
14
15<user-info>
16 <template scope="{username, sex, age}">
17 <h2>姓名:{{username}}</h2>
18 <h4>性别:{{sex}}</h4>
19 <h4>年龄:{{age}}</h4>
20 </template>
21</user-info>
适用于:数据在组件中定义,但根据数据生成的结构需要组件的使用者来决定。
评论