vue2 插槽:slot,slot-scoped,v-slot
vue2 插槽:slot,slot-scoped,v-slot。匿名插槽,具名插槽,作用域插槽
·
一、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 上 |
参考
更多推荐



所有评论(0)