一、vue中的插槽
1.1 vue中插槽要解决的问题
slot 插槽 ,是用在组件中,向组件分发内容。它的内容可以包含任何模板代码
,包括HTML
。它会解决下面的问题:
<template>
<div>
<p>buttonTest</p>
<my-button>
<!-- 处于自定义标签中的内容,如何呈现 -->
button
</my-button>
</div>
</template>
<script>
import MyButton from "./MyButton.vue";
export default {
components: {
"my-button": MyButton,
},
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
在自定义组件
中,标签中间的内容
如何呈现。
1.2 vue中插槽的发展
vue 在 2.6.0
中,具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot
指令)。它取代了 slot
和 slot-scope
这两个目前已被废弃但未被移除
且仍有用的特性。但是将会在vue 3
中,被废弃的这两个,不会被支持即无效
。
二、匿名插槽
<template>
<div>
<!-- slot里面也可以设置内容,这个可以设置不传内容时,slot有个默认值替换 -->
<slot>这里面是slot的默认值</slot>
</div>
</template>
<script>
export default {
name: "MyButton",
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
<template>
<div>
<p>buttonTest</p>
<my-button>
button
</my-button>
</div>
</template>
<script>
import MyButton from "./MyButton.vue";
export default {
name: "HelloWorld",
components: {
"my-button": MyButton,
},
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
- 匿名的方式,就是指把在
引用组件
的时候,里面传的内容
,全部一起
传送到组件页面中<slot></slot>
所在的位置。 - 只要组件中有
<slot></slot>
,并且不管有多少个
,都会全部渲染为传过来的内容
。意思就是说要是有多个<slot></slot>
,那么传过来的内容就会渲染多次
。 <slot></slot>
里面也可以设置内容,这个内容是保证引入组件的时候,有个默认值
。当然,<slot></slot>
里面不设置内容也可以,这样只是没有默认值,是不会报错
的。- 传递的内容,也可以是动态的。
- 如果传递的内容,
没有slot 来接收
,那么,传递的内容就会被抛弃掉
,不会起作用
。
三、具名插槽
<template>
<div>
<slot name="icon"></slot>
<slot name="content"></slot>
</div>
</template>
<script>
export default {
name: "MyButton",
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
<template>
<div>
<p>2.6.0以前的写法</p>
<my-button>
<!--2.6.0以前的写法-->
<template slot='icon'>
+
</template>
<template slot='content'>
新建
</template>
</my-button>
<p>--------------------------------------------</p>
<p>2.6.0之后的写法</p>
<my-button>
<!--2.6.0之后的写法-->
<template v-slot:icon>
+
</template>
<template v-slot:content>
新建
</template>
</my-button>
</div>
</template>
<script>
import MyButton from "./MyButton.vue";
export default {
name: "HelloWorld",
components: {
"my-button": MyButton,
},
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
具名插槽,就是给插槽指定名称,然后 一 一对应
- 2.6.0之前的版本
- 引入组件的页面,如果是多个内容,需要用
template
包裹起来,并且添加slot
属性和自定义值
。 slot 的值
需要和组件中<slot name='xxx'></slot>
name的值
相对应。- 如果
剩下的内容
没有包裹起来并制定值的话,那么这些内容会被渲染到 组件中所有的 <slot></slot>
所在的位置。 - 如果
slot 设置为default
和name 设置为default
,那就和没设置slot与name是一样的
。 - 和
vue 2.6.0
以后的具名插槽相比template
上的slot='xxx'
只需要 改成v-slot:xxx
就行了,等号改成了冒号
,并且值没有引号
,带引号反而会报错
。 - 具名插槽只需要
name值
与slot的值
对应 ,插槽的顺序是没有关系的
。
- 引入组件的页面,如果是多个内容,需要用
- 2.6.0之后的版本
v-slot
只能用在组件component
或者template
上 ,用在div
或p
这种标签上是会报错
的slot=' xxx '
改成了v-slot:xxx
,并且冒号后面这个名称不能打引号
- 组件页面中
slot
的内容没有变化 - 2.6.0 之后,具名插槽
v-slot:header
可以缩写为#header
,必须是有参数
才能这样写!#= "xxx "
这样是不行的,#default = 'xxx'
这样才可以
四、作用域插槽
<template>
<div>
<!--这里最重要的是 :anyName=value,anyName也是可以随便取的,表示要传过去的值-->
<slot name="icon" :anyName="defaultConfig"></slot>
<!--这里最重要的是 :anyName=value,anyName也是可以随便取的,表示要传过去的值-->
<slot name="content" :anyName="defaultConfig"></slot>
</div>
</template>
<script>
export default {
name: "MyButton",
props: {
},
data() {
return {
defaultConfig: {
icon: "+",
content: "新建",
},
};
},
methods: {
},
};
</script>
<template>
<div>
<p>2.6.0以前的写法</p>
<my-button>
<!--这里的anyName对应 slot 中传值 :name=value 中的 name-->
<template slot="icon" slot-scope="{ anyName }">
{
{ anyName.icon }}
</template>
<!--这里的obj是随便取的名称,不与任何地方对应-->
<template slot="content" slot-scope="obj">
{
{ obj.anyName.content }}
</template>
</my-button>
<p>--------------------------------------------</p>
<p>2.6.0之后的写法</p>
<my-button>
<!--这里的anyName对应 slot 中传值 :name=value 中的 name-->
<template v-slot:icon="{ anyName }">
{
{ anyName.icon }}
</template>
<!--这里的obj是随便取的名称,不与任何地方对应-->
<template v-slot:content="obj">
{
{ obj.anyName.content }}
</template>
</my-button>
</div>
</template>
<script>
import MyButton from "./MyButton.vue";
export default {
name: "HelloWorld",
components: {
"my-button": MyButton,
},
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
- 2.6.0之前的版本
- 作用域插槽主要是
使用子组件的任何数据
来达到自定义显示内容
的目的 - 作用域插槽最重要的一步,即是在
<slot></slot>
上绑定数据
,如果没有绑定数据
,则父组件收到的,只是一个空对象{}
。 - 作用域插槽中
<slot></slot>
上绑定数据,可以是写死的
,也可以是动态绑定的
。如果是动态绑定的,则也需要v-bind:xxx
- 作用域插槽中
<slot></slot>
上绑定的数据也可以传一个定义好的有返回值的 methods 方法
- 当
<slot></slot>
绑定上数据之后,引用组件的地方
中发送的内容就能通过slot-scope
来获取
。获取到的内容
,就是一个对象
slot-scope
可以接收任何有效
的可以出现在函数定义的参数位置上的JavaScript
表达式。
- 作用域插槽主要是
- 2.6.0之后的版本
两个属性
合并
成了一个v-slot:插槽名称='传过来的值'
。- 组件页面中
slot
的内容没有变化 。 v-slot
不能用在html
标签上 。- 如果是
默认插槽
,可以写成v-slot='xxx'
。
五、动态插槽名
动态指令参数也可以用在 v-slot
上,来定义动态的插槽名
:
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
六、插槽内容的解构赋值
v-slot
的值只要满足函数参数定义的 JavaScript
表达式的都可以接受。因此,在支持的环境(单文件或现代浏览器)中,你还可以使用 ES2015
解构语法
来提取特定的插值内容,例如:
<template>
<div>
<slot name="icon" :anyName="defaultConfig"></slot>
<slot name="content" :anyName="defaultConfig"></slot>
</div>
</template>
<script>
export default {
name: "MyButton",
props: {
},
data() {
return {
defaultConfig: {
add: {
icon: "+",
content: "新建",
},
},
};
},
methods: {
},
};
</script>
<template>
<div>
<my-button>
<template v-slot:icon="{ anyName }">
{
{ anyName.add.icon }}
</template>
<template v-slot:content="{ anyName: { add } }">
{
{ add.content }}
</template>
</my-button>
</div>
</template>
<script>
import MyButton from "./MyButton.vue";
export default {
name: "HelloWorld",
components: {
"my-button": MyButton,
},
props: {
},
data() {
return {
};
},
methods: {
},
};
</script>
七、2.6.0之前和之后的版本对比
2.6.0之前的版本 | 2.6.0之后的版本 | |
---|---|---|
匿名插槽 | 父组件:<template>content<template> 子组件: <slot></slot> |
父组件:<template>content<template> 子组件: <slot></slot> |
具名插槽 | 父组件:<template slot="slotName"><template> 子组件: <slot name="slotName"></slot> |
父组件:<template v-slot:slotName><template> 子组件: <slot name="slotName"> 简写: <template #slotName><template> |
作用域插槽 | 父组件:<template slot="slotName" slot-scope="obj"><template> 子组件: <slot name="slotName" :anyName="data"></slot> |
父组件:<template v-slot:slotName="obj"><template> 子组件: <slot name="slotName" :anyName="data"></slot> 简写: <template #slotName="obj"><template> |
使用位置 | 可用在任意标签,如:<p slot="slotName" slot-scope="data">{
{ data }}</p> |
只能用在 组件component 或者 template 上 |