1. 前言
本小节我们将介绍如何使用插槽slot
,包括默认插槽、具名插槽、作用域插槽。插槽可以使组件的模版变得多样性,让用户在使用组件时可以自定义传入模版内容。在复杂组件中,当我们在使用多个插槽的时候将会是一个难点。但只要我们将每个插槽类型的使用方法学透,相信面对任何复杂插槽的使用的时候都可以游刃有余。
2. 官方解释
Vue 实现了一套内容分发的 API,将 元素作为承载分发内容的出口。 —— 官方定义
<slot>
元素作为承载分发内容的出口,可以理解为一个占位符,或者说是子组件暴露的一个让父组件传入自定义内容的接口。插槽内可以包含任何模板代码,包括 HTML,甚至其他的组件。在工作中如果你的组件内的内容是可变的,这个时候我们可以考虑使用插槽。
3. 插槽的类型
<slot>
有三种类型,他们分别是:
- 默认插槽
default
- 具名插槽
name
- 作用域插槽
v-slot
接下来,我们将一步步介绍这三种不同插槽的使用方式。
3.1 默认插槽的使用
在自定义组件中使用<slot />
标签进行占位,当我们使用该组件时,在组件标签内写入需要展示的具体内容:
{components: {'MyConponent': {template: '<div><slot /></div>'}}}<my-conponent>这里是要显示的插槽内容!</my-conponent>{ components: { 'MyConponent': { template: '<div><slot /></div>' } } } <my-conponent>这里是要显示的插槽内容!</my-conponent>{ components: { 'MyConponent': { template: '<div><slot /></div>' } } } <my-conponent>这里是要显示的插槽内容!</my-conponent>
我们用一个简单的示例来学习以下如何使用默认插槽:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component>句号</my-component></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {template: '<div>Hello !<slot></slot></div>'})var vm = new Vue({el: '#app',data() {return {}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> 句号 </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div>Hello !<slot></slot></div>' }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> 句号 </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div>Hello !<slot></slot></div>' }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
代码解释:
在 JS 代码第 3-5 行,我们通过 Vue.Component 注册了全局组件 myComponent,并在组件内部使用了默认插槽 slot,在 html 中使用插槽(代码 2-4 行),并在标签内传入组件内需要展示的插槽内容。
3.2 具名插槽的使用
具名插槽就是给<slot />
标签加上 name
属性。语法:<my-component><slot name="插槽名字"/></my-component>
{components: {'MyConponent': {template: '<div><slot name="hello"/></div>'}}}<my-conponent><template slot="hello"></template></my-conponent>{ components: { 'MyConponent': { template: '<div><slot name="hello"/></div>' } } } <my-conponent> <template slot="hello"></template> </my-conponent>{ components: { 'MyConponent': { template: '<div><slot name="hello"/></div>' } } } <my-conponent> <template slot="hello"></template> </my-conponent>
我们用一个简单的示例,来学习一下如何使用具名插槽:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component><span slot="name">句号</span><span slot="time">2020-02-02</span></my-component></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {template: '<div>Hello !<slot name="name"></slot> <slot name="time"></slot></div>'})var vm = new Vue({el: '#app',data() {return {}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> <span slot="name">句号</span> <span slot="time">2020-02-02</span> </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div>Hello !<slot name="name"></slot> <slot name="time"></slot></div>' }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> <span slot="name">句号</span> <span slot="time">2020-02-02</span> </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div>Hello !<slot name="name"></slot> <slot name="time"></slot></div>' }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
代码解释:
在 JS 代码第 4-6 行,我们通过 Vue.Component 注册了全局组件 myComponent,并在组件内部使用了两个具名插槽 name 和 time,在 html 中使用具名插槽(代码 2-5 行),并在标签内传入组件需要展示的插槽内容。
3.3 作用域插槽的使用
有时候,我们在父组件使用插槽时需要访问子组件中的数据,这时候就需要使用作用域插槽。用法:将 data
变量名 作为 <slot>
元素的一个 attribute 绑定上去:
<slot :[自定义变量名]="[需要传入的数据]"></slot><!-- 示例 --><slot :count="count"></slot>```,在使用组件时,通过`v-slot:插槽名字="数据别名"`的方式使用。```html<!-- 默认插槽中使用作用域插槽 --><my-component><template v-slot:default="slotProps">{{slotProps.count}}</template></my-component><!-- 具名插槽中使用作用域插槽 --><my-component><template v-slot:插槽名字="slotProps">{{slotProps.count}}</template></my-component><slot :[自定义变量名]="[需要传入的数据]"></slot> <!-- 示例 --> <slot :count="count"></slot> ```, 在使用组件时,通过`v-slot:插槽名字="数据别名"`的方式使用。 ```html <!-- 默认插槽中使用作用域插槽 --> <my-component> <template v-slot:default="slotProps"> {{slotProps.count}} </template> </my-component> <!-- 具名插槽中使用作用域插槽 --> <my-component> <template v-slot:插槽名字="slotProps"> {{slotProps.count}} </template> </my-component><slot :[自定义变量名]="[需要传入的数据]"></slot> <!-- 示例 --> <slot :count="count"></slot> ```, 在使用组件时,通过`v-slot:插槽名字="数据别名"`的方式使用。 ```html <!-- 默认插槽中使用作用域插槽 --> <my-component> <template v-slot:default="slotProps"> {{slotProps.count}} </template> </my-component> <!-- 具名插槽中使用作用域插槽 --> <my-component> <template v-slot:插槽名字="slotProps"> {{slotProps.count}} </template> </my-component>
下面我们通过两个例子详细介绍,如何在默认插槽和具名插槽中,使用作用域插槽。
3.3.1 默认插槽中使用作用域插槽
对于默认插槽我们可以省略v-slot
后面的插槽名,直接使用v-slot="数据别名"
的方式:
示例:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component><!-- 使用 v-slot 接收默认插槽的数据,并把数据命名为 slotProps--><template v-slot:default="slotProps"><br /><!-- 使用 插槽数据-->我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}}</template></my-component><my-component><!-- 默认插槽可以忽略v-slot后面的插槽名--><template v-slot="slotProps"><br /><!-- 使用 插槽数据-->我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}}</template></my-component></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {// 在默认插槽中传入数据 detailtemplate: '<div>Hello !<slot :detail="detail"></slot></div>',data() {return {detail: {name: '句号',love: 'coding'}}}})var vm = new Vue({el: '#app',data() {return {}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> <!-- 使用 v-slot 接收默认插槽的数据,并把数据命名为 slotProps--> <template v-slot:default="slotProps"> <br /> <!-- 使用 插槽数据--> 我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}} </template> </my-component> <my-component> <!-- 默认插槽可以忽略v-slot后面的插槽名--> <template v-slot="slotProps"> <br /> <!-- 使用 插槽数据--> 我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}} </template> </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { // 在默认插槽中传入数据 detail template: '<div>Hello !<slot :detail="detail"></slot></div>', data() { return { detail: { name: '句号', love: 'coding' } } } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> <!-- 使用 v-slot 接收默认插槽的数据,并把数据命名为 slotProps--> <template v-slot:default="slotProps"> <br /> <!-- 使用 插槽数据--> 我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}} </template> </my-component> <my-component> <!-- 默认插槽可以忽略v-slot后面的插槽名--> <template v-slot="slotProps"> <br /> <!-- 使用 插槽数据--> 我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}} </template> </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { // 在默认插槽中传入数据 detail template: '<div>Hello !<slot :detail="detail"></slot></div>', data() { return { detail: { name: '句号', love: 'coding' } } } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
代码解释:
在 JS 代码第 3-14 行,我们通过 Vue.Component 注册了全局组件 myComponent。
在 HTML 代码第 2-8 行,使用 v-slot:default=“数据别名” 的方式接收默认插槽的数据,并把数据命名为 slotProps。
在 HTML 代码第 9-16 行,使用 v-slot=“数据别名” 的方式接收默认插槽的数据(省略默认插槽名),并把数据命名为 slotProps。
3.3.2 具名插槽中使用作用域插槽
具名插槽必须在v-slot
后面加上插槽名,否则数据无法在具名插槽中使用:
示例:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component><!-- 使用 v-slot 接收具名插槽 detail 的数据,并把它命名为 slotProps--><template v-slot:detail="slotProps"><br /><!-- 使用 插槽 detail 的数据-->我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}}</template></my-component></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {// 定义具名插槽 detail 并传入数据 detailtemplate: '<div>Hello !<slot :detail="detail" name="detail"></slot></div>',data() {return {detail: {name: '句号',love: 'coding'}}}})var vm = new Vue({el: '#app',data() {return {}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> <!-- 使用 v-slot 接收具名插槽 detail 的数据,并把它命名为 slotProps--> <template v-slot:detail="slotProps"> <br /> <!-- 使用 插槽 detail 的数据--> 我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}} </template> </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { // 定义具名插槽 detail 并传入数据 detail template: '<div>Hello !<slot :detail="detail" name="detail"></slot></div>', data() { return { detail: { name: '句号', love: 'coding' } } } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component> <!-- 使用 v-slot 接收具名插槽 detail 的数据,并把它命名为 slotProps--> <template v-slot:detail="slotProps"> <br /> <!-- 使用 插槽 detail 的数据--> 我叫:{{slotProps.detail.name}},我的爱好是:{{slotProps.detail.love}} </template> </my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { // 定义具名插槽 detail 并传入数据 detail template: '<div>Hello !<slot :detail="detail" name="detail"></slot></div>', data() { return { detail: { name: '句号', love: 'coding' } } } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
在 JS 代码第 3-14 行,我们通过 Vue.Component 注册了全局组件 myComponent。
在 HTML 代码第 2-8 行,使用 v-slot:default=“数据别名” 的方式接收默认插槽的数据,并把数据命名为 slotProps。
暂无评论内容