一、概念
要了解 slot 插槽 , 首先需要了解自定义组件,以及组件中的模板
举例:
自定义一个组件名 tag1
//组件模板为
var tag1mes = {
template:`<dl>
<dt>狮子</dt>
<dd>是一种生存在非洲与亚洲的大型猫科动物</dd>
</dl>`
}
...定义一个局部组件
components:{
tag1:tag1mes
}
...
在结构中加入这个组件<tag1></tag1>,利用浏览器调试工具,可以看到渲染的结构为
<dl>
<dt>狮子</dt>
<dd>是一种生存在非洲与亚洲的大型猫科动物</dd>
</dl>
此时此刻,如果我们想进一步丰富template模板中展示内容的灵活性,可以借助插槽slot
需求:如果我们想把模板中的狮子替换成老虎
二、如何实现?
匿名插槽
<tag1>老虎</tag1> //将要写的内容写在标签内,像HTML标签一样
var tag1mes = {
template:`<dl>
<dt><slot></slot></dt> //添加的位置上,增加<slot></slot>标签
<dd>是一种生存在非洲与亚洲的大型猫科动物</dd>
</dl>`
}
渲染后,狮子就变成老虎了
此外可以添加默认值
var tag1mes = {
template:`<dl>
<dt><slot>狮子</slot></dt> //slot中为默认值
//slot中的是默认的,<tag1>标签内为用户设置的,【设置没有显示默认,设置有,显示设置的】
<dd>是一种生存在非洲与亚洲的大型猫科动物</dd>
</dl>`
}
呈现效果
<tag1>老虎</tag1>,渲染标题为老虎,
<tag1></tag1> 渲染结果为,默认的狮子,
最后,由于这种<slot></slot>插槽没有name属性,因此叫【匿名插槽】
具名插槽
需求:如果不仅替换标题,还要替换标题的内容描述,怎么办?
显然
<tag1> 老虎, 大型猫科动物;毛色浅黄或棕黄色,满身黑色横纹;头圆、耳短,耳背面黑色,中央有一白斑甚显著。 </tag1>
怎么分开对应dt,dd标签是个问题
这时候可以使用具名插槽,见例子
<tag1 :fatherdata="fatherdata">
<template slot="tit">老虎</template>
<template slot="mes">大型猫科动物;毛色浅黄或棕黄色,满身黑色横纹;头圆、耳短,耳背面黑色,中央有一白斑甚显著。</template>
</tag1>
template:` <dl>
<dt><slot name="tit">狮子</slot></dt>
<dd><slot name="mes">是一种生存在非洲与亚洲的大型猫科动物</slot></dd>
</dl>`
通过slot name的属性,将template slot="name名" 一一对应起来
三、新版本语法 v-slot
Vue的版本官方一直在更新变化,其中上面使用的 slot="xx" 以及后面会提及的 scope-slot="xx" 在2.6.0+ 中已弃用
所以我们要使用新的v-slot
语法格式
v-slot:slotName //slotName不能加双引号“”
匿名插槽在新语法下,默认指向default
v-slot:default
例子修改,结果仍然正常
<tag1 :fatherdata="fatherdata">
<template v-slot:tit>老虎</template>
<template v-slot:mes>大型猫科动物;毛色浅黄或棕黄色,满身黑色横纹;头圆、耳短,耳背面黑色,中央有一白斑甚显著。</template>
</tag1>
注意事项
在旧版本中slot="xxx"的情况下,可以挂载在非 template标签上,如:
<p slot="tit">老虎</p>
但是在v-slot:tit的情况下,必须使用template标签
<template v-slot:tit>老虎</template>
否则报错:
Failed to compile.
v-slot can only be used on components or <template>.
简写方式
如果你想使用简写语法,必需指定插值的名字
v-slot:header 简写成 #header
v-slot:default 简写成 #default
四、作用域插槽
意义何在?
如果你想 父组件访问子组件内部数据
语法格式:旧版本 slot-scope
slot-scope="slotProps" //slotProps为自定义的变量名,指向子组件中的data函数返回值
针对上面例子
//新旧语法不能混用在一个组件标签上
//slot="xxx" slot-scope="xx" 均为旧写法,是可以的
//v-slot:xxx slot-scope="xxx" 新旧写法混合,直接报错
//渲染错误: Unexpected mixed usage of different slot syntaxes
<tag1>
<template slot="tit" slot-scope="slotProps">
{{slotProps.txt1}}
</template>
<template v-slot:mes></template>
</tag1>
var tag1mes = {
data:function(){
return {
txt1:'我是子组件里的数据: 猫头鹰'
}
},
template:` <dl>
<dt><slot name="tit" v-bind:txt1="txt1">狮子</slot></dt>
<dd><slot name="mes">是一种生存在非洲与亚洲的大型猫科动物</slot></dd>
</dl>`
}
新语法格式为
v-slot:tit="slotProps" //slotProps为自定义的变量名,指向子组件中的data函数返回值
//将具名插槽赋值,很简洁;
//不仅完成插槽指向,还完成了数据挂载
例子改写:
<tag1>
<template v-slot:tit="slotProps">
{{slotProps.txt1}}
</template>
<template v-slot:mes></template>
</tag1>
var tag1mes = {
data:function(){
return {
txt1:'我是子组件里的数据: 猫头鹰'
}
},
template:` <dl>
<dt><slot name="tit" v-bind:txt1="txt1">狮子</slot></dt>
<dd><slot name="mes">是一种生存在非洲与亚洲的大型猫科动物</slot></dd>
</dl>`
}
上结果
作用域插槽图解
父组件访问子组件内部数据
插槽父子之间传值 2.6+
父组件
<template #swiperSlide='{dataMes}'>
...
</template>
子组件
<slot
name="swiperSlide"
:dataMes='dataMes'
></slot>
说明:
父组件通过 #slotName 获取子组件 ,
通过 { 数据名 } 获取子组件中的数据