插槽是什么?
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”。以下举例子帮助理解。
分类
vue的插槽有三种:分别是默认插槽、具名插槽、作用域插槽
插槽
-
默认情况下,使用组件的时候不能在组件标签内填充内容的
-
插槽的作用:在使用组件的时候,在组件标签内填充的内容,能成功渲染
<template id="info"> <div> <p>我是组件</p> </div> </template><div id="app"> <info> <!--在使用组件时,填充的内容不能渲染--> <P>使用组件标签时填充的元素</P> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", }, }, });
插槽的使用
-
定义组件的时候使用slot标签在组件内部”留坑“,那么在使用组件的时候,填充的内容就会渲染在坑上
-
在使用slot标签留坑的时候也可以指定坑内的默认内容,如果指定了坑的默认内容,那么在使用组件的时候没有填充内容,则渲染slot标签的默认内容。如果指定了坑的默认内容,那么在使用组件的时候填充内容,则渲染填充内容。
<template id="info"> <div> <p>我是组件</p> <!--使用solt标签在组件内容留坑处理--> <slot> <!--并且可以指定默认的填充内容,也可以不指定默认的填充内容--> <p>我是组件坑内的内容</p> </slot> </div> </template><div id="app"> <info> <!-- 1.在使用组件时,填充了内容就会显示填充的内容 2.如果没有填充内容就会显示组件slot标签的默认内容 --> <P>使用组件标签时填充的元素</P> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", }, }, });
slot标签注意点
-
默认一对slot标签就会渲染一次组件填充的全部内容,多次slot标签则渲染多次
<template id="info"> <div> <p>我是组件</p> <!--两对slot标签就会渲染填充的内容两次--> <slot> <p>我是组件坑内的内容</p> </slot> <slot> <p>我是组件坑内的内容</p> </slot> </div> </template><div id="app"> <info> <P>使用组件标签时填充的元素</P> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", }, }, });
插槽的命名
-
给slot标签添加name属性可以指定插槽的名称
-
使用的时候需要给填充的内容绑定slot="插槽名称",填充到指定的插槽
<template id="info"> <div> <p>我是组件</p> <slot name="one"> <p>我是组件坑内的内容</p> </slot> <slot name="two"> <p>我是组件坑内的内容</p> </slot> </div> </template><div id="app"> <info> <!--这种填充方式存在指令属性冗余问题,因为需要多次绑定slot属性--> <P slot="one">使用组件标签时填充的内容1</P> <P slot="one">使用组件标签时填充的内容11</P> <P slot="one">使用组件标签时填充的内容111</P> <P slot="two">使用组件标签时填充的内容2</P> <P slot="two">使用组件标签时填充的内容22</P> <P slot="two">使用组件标签时填充的内容222</P> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", }, }, }); -
使用v-slot指令和template标签解决上述问题
<template id="info"> <div> <p>我是组件</p> <slot name="one"> <p>我是组件坑内的内容</p> </slot> <slot name="two"> <p>我是组件坑内的内容</p> </slot> </div> </template><div id="app"> <info> <template v-slot:one> <P>使用组件标签时填充的内容1</P> <P>使用组件标签时填充的内容11</P> <P>使用组件标签时填充的内容111</P> </template> <template v-slot:two> <P>使用组件标签时填充的内容2</P> <P>使用组件标签时填充的内容22</P> <P>使用组件标签时填充的内容222</P> </template> <!--简写--> <template #one> <P>使用组件标签时填充的内容1</P> <P>使用组件标签时填充的内容11</P> <P>使用组件标签时填充的内容111</P> </template> <template #two> <P>使用组件标签时填充的内容2</P> <P>使用组件标签时填充的内容22</P> <P>使用组件标签时填充的内容222</P> </template> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", }, }, });
具名插槽
- 匿名插槽没有name属性,所以是匿名插槽,那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次。出现在不同的位置。下面的例子,就是一个有两个具名插槽和单个插槽的组件,这三个插槽被父组件用同一套css样式显示了出来,不同的是内容上略有区别。
父组件:
<template>
<div class="father">
<h3>这里是父组件</h3>
<child>
<div class="tmpl" slot="up">
<span>菜单1</span>
<span>菜单2</span>
<span>菜单3</span>
<span>菜单4</span>
<span>菜单5</span>
<span>菜单6</span>
</div>
<div class="tmpl" slot="down">
<span>菜单-1</span>
<span>菜单-2</span>
<span>菜单-3</span>
<span>菜单-4</span>
<span>菜单-5</span>
<span>菜单-6</span>
</div>
<div class="tmpl">
<span>菜单->1</span>
<span>菜单->2</span>
<span>菜单->3</span>
<span>菜单->4</span>
<span>菜单->5</span>
<span>菜单->6</span>
</div>
</child>
</div>
</template>
子组件:
<template>
<div class="child">
// 具名插槽
<slot name="up"></slot>
<h3>这里是子组件</h3>
// 具名插槽
<slot name="down"></slot>
// 匿名插槽
<slot></slot>
</div>
</template>
可以看到,父组件通过html模板上的slot属性关联具名插槽。没有slot属性的html模板默认关联匿名插槽。
作用域插槽
-
用域插槽就是带数据的插槽, 就是让父组件在填充子组件插槽内容时也能使用子组件的数据
-
子组件通过v-bind指令传递
-
父组件通过slot-scope接收
<template id="info"> <div> <p>我是组件</p> <slot v-bind:names= "name"></slot> </div> </template><div id="app"> <info> <template slot-scope="obj"> <P>使用组件标签时填充的元素 {{ obj.names }}</P> </template> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", data: function () { return { name: "lnj", } } }, }, }); -
整合优化:使用v-slot指令
<template id="info"> <div> <p>我是组件</p> <slot v-bind:names= "name"></slot> </div> </template><div id="app"> <info> <!-- 1.v-slot:插槽名称="通过什么变量接收" 2.数据会以对象的形式保存到变量中 3.匿名插槽的名称为default --> <template v-slot:default="obj"> <P>使用组件标签时填充的元素 {{ obj.names }}</P> </template> </info> </div>new Vue({ el: '#app', components:{ "info":{ template:"#info", data: function () { return { name: "lnj", } } }, }, });
在 2.6.0 中,为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC。注意slot版本变化,vue2中仍可以使用slot与slot-scope,但是vue3只能使用v-slot了,切记,避免踩坑。
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。