Vue- 插槽 (slot) 的使用
插槽(slot)
插槽在 vue 中是一种很常见的写法,让父组件可以向子组件指定位置插入 html 结构,也是一种组件间通信的方式
一共有三种分类:默认插槽、具名插槽、作用域插槽,下面一一根据案例改造说明
1 基本案例
首先编写一个基本的案例,三个组件展示不同的数据类型

页面进行展示

现在要改需求,美食的列表只展示一个海报图片,电影则展示一段宣传视频,游戏则不变
如果要按照美食的需求去改统一加上照片

那么三个列表都有了这个照片

当然可以使用 v-show 判断

虽然可以实现效果,但是比较麻烦,而且电影的列表如果也按照这样判断,那么代码维护性特别低,逻辑非常混乱

这时候就可以使用插槽了
2 插槽的基本使用
所谓插槽,其实就是挖个坑,等着使用者进行填充
下面的案例是一个最基本的单个插槽使用,也叫默认插槽
比如下面我改造了下代码,在组件标签里面写一个 doc 元素

但是查看的时候发现什么都没有

这是因为虽然定义了元素,但是 vue 不知道去组件哪个地方填充,这个时候我们需要在被需要填充的组件里面定义一个插槽(slot)标签


这样我就可以只需要一个插槽,对不同的组件进行不同的元素展示了,如下

图片,列表,视频,我想要什么就定义什么,组件只需要一个插件接收即可,这样就能实现动态展示同一个组件不同的数据

值得注意点是,虽然通过组件标签把数据和资源传输到了组件中并使用插槽进行展示,但是都是通过 app 这个组件进行传输的,所以对元素的样式控制,完全可以在 app.vue 里面处理完之后再传递

当然如果非要把样式在用到插槽的组件中进行处理,也是没问题的

不管在那处理,都是一样的

插槽的默认值
插槽是可以定义默认值的,当没有对插槽进行填充的时候,就会展示默认值,如下所示我把组件里面的内容注释掉了,这时候就会出现插槽的默认值:

图片被默认值取代了

3 具名插槽
默认插槽是插槽家族中最简单的使用方式,下面的具名插槽则是比它稍微复杂些的一个使用方式
顾名思义,它指的是具有名字的插槽
所以改下上面的需求,在原有的基础上,加入更多的元素,通过另外一个插槽实现,也就是多个插槽
如果直接复制一个默认插槽,肯定是不行的

发现全部的元素都出现了两份,这不是我们想要的效果

插槽确实需要些多个,但是需要 name 指定插槽的名称

但是发现还是不行

因为虽然给插槽命名了名称,但是插入内容的时候并没有告诉对应的插槽,所以需要使用 slot 属性去标识具体的插槽


多个插值小技巧
如果有多个元素需要使用同一个插槽是不会进行数据覆盖的,这种情况我们可以定义一个 div,然后在 div 中指定插槽的 name


一样的效果

template 使用技巧
如果想要多个元素并且不想再多生成一个无用的 div,可以使用 template 标签


template 的 v-slot 写法
一旦使用了 template 标签,就有了第二种写法了,这是 vue2.6 提出来的,v-slot:xxx

v-slot 的写法只能作用于 template 标签上,不信你看,这里我加到了 div 身上

直接报错了

以上就是具名插槽的用法了
4 作用域插槽
说完了默认插槽和具名插槽,接下来就是插槽的最后一种用法:作用域插槽
说到作用于大多数人想到的是 js 的作用域,这个作用域插槽还真和 js 的作用域有几分相似
现在有一个需求,根据菜单生成的数据还是一样的数据,但是展示方式不同

比如第一个列表还是无序的,第二个列表是有序的,第三个列表则要把游戏名称以 h4 的形式展现
这时候就可以借助作用域插槽了
如果正常写

会报错,表示找不到 games

这就是一个作用域的问题,我们传递了 games,需要在接收方定义 template 使用 scope 属性进行接收


另外一种写法
老是写传递的参数有点烦,就可以使用这种写法

传递多个属性
不止可以传递一个属性,比如:


效果都是一样的
5 插槽总结
作用:让父组件可以向子组件指定位置插入 html 结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。
分类:默认插槽、具名插槽、作用域插槽
使用方式:
1 默认插槽:
父组件中:<Category><template slot="center"><div>html 结构 1</div></template>
版权声明: 本文为 InfoQ 作者【张三丰无极】的原创文章。
原文链接:【http://xie.infoq.cn/article/3d3af2cf1f645d42b9f58edc1】。文章转载请联系作者。
评论