今天来分享一下vue中的slot插槽,常用elementUI的同学肯定不会陌生,特别是在用表单组件或table组件的时候,插槽的作用也被充分体现出来。
提示:本篇文章所有例子都基于vue-cli脚手架,且vue的版本是2.6.0以上。文中代码只是关键代码。
插槽,我们想象一下电脑的主板,主板上面有很多插槽,而每个插槽可能对应了不同的配置,那么在vue中,也可以这么来理解,各个插槽有各个插槽的功能,它们相互独立,可用于组件之间通信。
插槽分别有匿名插槽、具名插槽以及作用域插槽,下面分别用例子来体现它们的区别和用法。
一、匿名插槽
匿名插槽,简单来说就是没有命名的插槽,它的创建方式很简单,来看看这个例子:
// 父组件中
<lay-out>这是匿名插槽</lay-out>
// 子组件中
<slot></slot>
在父组件中的子组件标签内编辑内容,然后在子组件中使用slot标签直接接收该内容,来看页面效果:
![70bb06b455946a42d321e525d71d494f.png](https://img-blog.csdnimg.cn/img_convert/70bb06b455946a42d321e525d71d494f.png)
既然父组件可以通过插槽传递一个字符串给子组件,那么也可以传递一个属性值,来看下面这段代码:
// 父组件中
<lay-out>{{slotName}}</lay-out>
data () {
return {
slotName: '这是父组件传给子组件的'
}
}
// 子组件中
<slot></slot>
上面例子父组件在子组件标签内调用父组件中的一个属性,这个属性将通过插槽传递到子组件中,来看结果:
![179d9300816f953d359d515e6ef38345.png](https://img-blog.csdnimg.cn/img_convert/179d9300816f953d359d515e6ef38345.png)
在vue2.6.0及以上版本中,插槽使用v-slot属性,但这个属性只能写到模板标签<template>上,v-slot标签可以绑定插槽的名字,也可以不用绑定,当不绑定名字的时候,它依然是匿名插槽,我用v-slot改写一下上一个例子:
// 父组件中
<lay-out>
<template v-slot:default>{{slotName}}</template>
</lay-out>
data () {
return {
slotName: '这是父组件传给子组件的'
}
}
// 子组件中
<slot></slot>
页面结果我就不贴了,跟上一个例子中的效果一样。v-slot:XX=””冒号后面的就是插槽名,配合具名插槽使用,如果是匿名插槽,就是default,而右边引号内部就是用来处理作用域插槽的,这个放到最后来说。
接下来,就是具名插槽了,具名插槽很明显就是具有命名的插槽,父组件可以通过插槽名来定位到是哪一个插槽,从而定向传递相应的数据,来看看例子:
// 父组件中
<lay-out>
<template v-slot:content>这是具名插槽</template>
</lay-out>
// 子组件中
<slot name="content"></slot>
子组件的slot标签上绑定一个name属性,name属性的值就是这个插槽的名字,然后父组件中在子组件标签中的模板标签上使用v-slot属性绑定这个插槽名,这时子组件和父组件之间就连接上了。来看看效果:
![f2d40419beb4833a2e61df6983b0e4d9.png](https://img-blog.csdnimg.cn/img_convert/f2d40419beb4833a2e61df6983b0e4d9.png)
红色部分就是具名插槽模块。
最后来看看作用域插槽,作用域插槽我用一句话概括就是扩充父组件访问子组件中属性的权限的一个方法。想象一下,我们把父组件看作为一个函数外部的作用域,而子组件就是函数内部的局部作用域,外部作用域是无法直接访问到局部作用域中的变量的。而这里,父组件也同样无法直接访问到子组件中的属性,先来看个测试:
// 子组件中
<slot name="footer"></slot>
data () {
return {
navName: '这是作用域插槽'
}
}
// 父组件中
<lay-out>
<template v-slot:footer>{{navName}}</template>
</lay-out>
子组件中有个navName属性,父组件中要拿到子组件这个属性,直接拿,来看看结果:
![6c1a8b017a2f98b44c14577e1b2daa9e.png](https://img-blog.csdnimg.cn/img_convert/6c1a8b017a2f98b44c14577e1b2daa9e.png)
控制台直接抛出属性未定义错误,证明是不能直接拿到子组件中的属性的。想要获取到子组件中的属性,需要在子组件的slot标签上绑定该属性,再回到父组件中获取这个属性,我稍微改一下上面这段代码:
// 子组件中
<slot name="footer" :navFooter="navName"></slot>
data () {
return {
navName: '这是作用域插槽'
}
}
// 父组件中
<lay-out>
<template v-slot:footer="slotProps">{{slotProps.navFooter}}</template>
</lay-out>
理一下这段代码,子组件中在slot标签上绑定一个自定义navFooter属性来存储子组件中的某个属性,再在父组件的子组件标签上使用v-slot属性的props来获取到子组件传过来的属性。来看看效果:
![4660aca9c0d4d0d0bb5d3bbd9dfbfeb5.png](https://img-blog.csdnimg.cn/img_convert/4660aca9c0d4d0d0bb5d3bbd9dfbfeb5.png)
最后一条就是采用作用域插槽渲染的模块,效果没问题。
上面这个作用域插槽还有一个简单的方式来编写,在v-slot属性中,可以才用解构赋值方式拿到子组件传过来的属性,下面是修改部分的代码:
<template v-slot:footer="{navFooter}">{{navFooter}}</template>
这种解构赋值的方法得到的效果也是和上面一样,但这种写法更加简洁。
前面我分享了一篇vue组件通信的文章,而这篇是vue插槽,插槽本质上也是组件通信,光靠这两篇文章,学起来太没意思了,那就来个小案例,篇幅会比较大,我就放到下一篇分享啦~