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>
在自定义组件
中,标签中间的内容
如何呈现。
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>
具名插槽,就是给插槽指定名称,然后 一 一对应
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的值
对应 ,插槽的顺序是没有关系的
。v-slot
只能用在组件component
或者 template
上 ,用在 div
或p
这种标签上是会报错
的slot=' xxx '
改成了v-slot:xxx
,并且冒号后面这个名称不能打引号
slot
的内容没有变化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>
使用子组件的任何数据
来达到自定义显示内容
的目的<slot></slot>
上绑定数据
,如果没有绑定数据
,则父组件收到的,只是一个空对象{}
。<slot></slot>
上绑定数据,可以是写死的
,也可以是动态绑定的
。如果是动态绑定的,则也需要v-bind:xxx
<slot></slot>
上绑定的数据也可以传一个定义好的有返回值的 methods 方法
<slot></slot>
绑定上数据之后,引用组件的地方
中发送的内容就能通过slot-scope
来获取
。获取到的内容
,就是一个对象
slot-scope
可以接收任何有效
的可以出现在函数定义的参数位置上的JavaScript
表达式。两个属性
合并
成了一个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之后的版本 | |
---|---|---|
匿名插槽 | 父组件:<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 上 |