一、插槽介绍
插槽(slot)本质是组件的一段HTML模版。插槽显不显示由父组件决定。
插槽的核心问题就是:(1)显不显示;(2)怎么显示
一个组件中的非插槽模版是指html模版:div、span、ul、table等;非插槽模板的显示隐藏以及怎样显示由自身控制
插槽模版其实就是空壳子,因为它显示隐藏以及最后用什么样的html模板显示是由父组件控制;但是插槽显示的位置确由子组件自身决定,slot写在子组件template的哪块,父组件传过来的模板将来就显示在哪块
插槽分类
- 单个插槽(也称为匿名插槽或默认插槽)
- 具名插槽
- 作用域插槽
二、单个插槽
这种插槽不用设置name属性,可以放置在组件的任意位置,一个组件中只能有一个“单个插槽”
父组件
父组件中使用了子组件child,并定义了html模版。该html模版会在子组件的匿名插槽位置显示出来
<template>
<div class="father">
<h3>这里是父组件</h3>
<child>
<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">
<h3>这里是子组件</h3>
<slot></slot>
</div>
</template>
最终的渲染结果如图所示:
三、具名插槽
插槽加了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模板默认关联匿名插槽
四、作用域插槽
作用域插槽要求在slot上面绑定数据
<slot name="up" :data="data"></slot>
export default {
data: function(){
return {
data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
}
},
}
前面说了,插槽最后显不显示是看父组件有没有在child组件下面写模板,像下面这样
<child>
html模板
</child>
因为作用域插槽绑定了一套数据,父组件可以拿来使用。于是,情况变成了这样:样式父组件说了算,但是内容可以显示子组件插槽绑定的
作用域插槽与其他两种插槽的区别:
单个插槽和具名插槽不绑定数据,所以父组件提供的模版既包括样式,也包括数据内容;
作用域插槽中,父组件只需要提供一套样式
父组件
<template>
<div class="father">
<h3>这里是父组件</h3>
<!--第一次使用:用flex展示数据-->
<child>
<template slot-scope="user">
<div class="tmpl">
<span v-for="item in user.data">{{item}}</span>
</div>
</template>
</child>
<!--第二次使用:用列表展示数据-->
<child>
<template slot-scope="user">
<ul>
<li v-for="item in user.data">{{item}}</li>
</ul>
</template>
</child>
<!--第三次使用:直接显示数据-->
<child>
<template slot-scope="user">
{{user.data}}
</template>
</child>
<!--第四次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
<child>
我就是模板
</child>
</div>
</template>
子组件
<template>
<div class="child">
<h3>这里是子组件</h3>
// 作用域插槽
<slot :data="data"></slot>
</div>
</template>
export default {
data: function(){
return {
data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
}
}
}
结果如下图所示:
五、其他知识点
5.1 slot 与 slots 的区别
slot用来定义插槽,slots相当于refs的用法,用来获取vue组件中定义的slot,实现内容分发
5.2 slot-scope介绍
slot-scope代表的是子组件绑定的数据属性
5.3 v-slot
v-slot命令是slot和slot-scope的替代
格式如下:
v-slot:title="nodeData"
v-slot:插槽名称=子组件内部绑定数据(nodeData可以随意起名)