一vue中插槽详解---从slot,slot-scope到v-slot的变化
作者:互联网
前言
vue 插槽,目前到3.0有3种方式,第一种,在2.6之前使用的是slot 和 slot-scpe 2.6后已被官方废弃,但在2.x版本仍被支持,第二种是vue 在2.6版本后更新的新指令 v-slot 来替代slot 和slot-scpe
那么什么是插槽呢,作用又是什么
插槽,简单说,插槽就是杯子,杯子里面装的是饮料还是牛奶,由外部倒入什么来决定 ,就好比下面的代码,我需要一个子组件,他有部分内容,需要根据我当前页面需要来展示,我如何将html模板传人到子组件就需要使用插槽。
所以我定义了一个子组件item,我用solt标签定义了一个默认插槽,为在父组件使用时,需要传递到item组件的模板,占个位置, 这样我在组件,使用item子组件,在其中编写,html模板就会被渲染到子组件
默认插槽
父组件
<template>
<tab>
<item >
<div>装一杯牛奶</div>
<item>
<tab>
</template>
//item子组件
<template>
<div>
<slot ></slot>//默认插槽 在父组件使用item子组件,item标签包裹的内容将默认被渲染到子组件的 solt中
<h1>
我是杯子
</h1>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
这样的好处,显而易见,可以让组件模块化更清晰,同时复用性更高,不至于,我要一杯茶,我就要定义一个组件,我要一杯牛奶我又定义一个组件,有了插槽,我只需要定义一个杯子,要喝什么由使用的传人决定。
上述代码也叫默认插槽,就是默认把模板全部渲染到solt中,如果需要指定渲染,就需要使用具名插槽,简单说就是起一个名字,告诉他小红该坐那儿,小明该坐那儿
具名插槽
//父级
<template>
<div>
<layout>
<div solt="header">头部标题</div>
<div >显示的内容</div>
<div slot="footer">尾部</div>
</layout>
</div>
</template>
//layout子组件
<template>
<div>
<layout>
<h1>layout子组件</h1>
<slot name="header"></slot> //这种就叫具名插槽
<slot></slot> //如果不指定名字,就会将模板中未匹配到的内容渲染到默认插槽中,这里为显示的内容
<slot name="footer"></slot>
</layout>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**tip:**当你的子组件中 如layout 中并不存在,slot这个元素,那么在父页面中 这个标签中的内容都会被抛弃
作用域插槽
父组件提供了模板给子组件,那么子组件如何反馈给父组件呢,例如:我定义了一个杯子,我需要告诉使用的人,我这个杯子,只能装300mL,这时我们就需要用slot-scope来接收子组件上通过v-bind绑定的值。
作用域插槽,就是能让插槽内容访问到子组件中才有的数据
//父级
<template>
<div>
<cup>
<div solt="size" slot-scope="data">
{{data.msg}}
</div>
</cup>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
//cup子组件
<template>
<div>
<slot name="size" :msg="msg"></slot>
</div>
</template>
<script>
export default {
data(){
return{
msg:'300mL大小的杯子'
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
解构prop的写法
下面写法等同上面
//父级
<template>
<div>
<cup>
<div slott="size" slot-scope="{msg}">
{{msg}}
</div>
</cup>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
上述是vue2.6之前的版本,之后vue官方废弃了上面的语法,改为v-solt来代替,然后大家就想知道,区别在哪呢
首先就是 用一个指令合并了solt 和solt-scope2个attribute,写法更加简洁,其次就是语义化更明显
2.6之前的写法会出现作用域混淆的问题
例:
<one>
<two slot-scope="one"> //接受到的作用域,是外层one组件的,而不是当前组件two
<three slot-scope="two">
<template slot-scope="three">
{{ one }} {{ two }} {{ three }}
</template>
</three>
</two>
</one>
1
2
3
4
5
6
7
8
9
如上述代码一层子组件时,你能清晰的看清作用域是哪一个组件的,但多层嵌套后,每一层接收的作用域是外层组件的而不是当前组件的,这样,就会不清晰,所以vue希望能实现,当前组件,接受当前组件的作用域
于是就有了v-solt 下面是改良后的代码,是否更加的清晰了
<one v-slot="one">
<twotwo v-slot="two"> //接收到的作用域为当前two组件的
<three v-slot="three">
{{ one }} {{ two }} {{ three }}
</three>
</bar>
</one>
1
2
3
4
5
6
7
如果没看懂 那么下面来阐述,v-solt的使用变化,
v-solt 默认插槽
和原来不同便是,原来的solt属性可以定义在任何元素上,现在v-solt只能是template元素上,只有一种额外情况,就是独占默认插槽,我们先看常规情况。v-slot:default这种就是具名的写法
父组件
<template>
<item >
<template v-slot:default> // v-slot:default可以不加,只能定义在template上
<div>装一杯牛奶</div>
</template>
<item>
</template>
//item子组件
<template>
<div>
<slot ></slot>//默认插槽
<h1>
我是杯子
</h1>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
未具名的solt 元素,自动默认名为default 你可以不写,当然如果你要看的更清晰,
独占默认插槽
提供内容只有默认插槽,上述就满足此条件,所以我们可以这样写
父组件
<template>
<item v-slot:default> //v-slot:default可以不加
<div>装一杯牛奶</div>
<item>
</template>
//item子组件
<template>
<div>
<slot ></slot>//默认插槽
<h1>
我是杯子
</h1>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
v-solt具名插槽
//父级
<template>
<div>
<layout>
<template v-slot:header>//v-slot指令使用插槽
<div >头部标题</div>
</template>
<div >显示的默认内容</div>
<!--
或者
<template v-slot:default>
<div >显示的默认内容</div>
</template>
-->
<template v-slot:footer>
<div >尾部</div>
</template>
</layout>
</div>
</template>
//layout子组件
<template>
<div>
<layout>
<h1>layout子组件</h1>
<slot name="header"></slot> //这种就叫具名插槽
<slot></slot> //如果不指定名字,就会将模板中未匹配到的内容渲染到默认插槽中,这里为显示的内容
<slot name="footer"></slot>
</layout>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
v-solt作用域插槽
这是改动最大地方
//父级
<template>
<div>
<cup>
<template v-slot:default="data"> //具名写法
<div>
{{data.msg}}
</div>
</template>
<!--
或者
<template v-slot="data">
<div > {{data.msg}} </div>
</template>
-->
</cup>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//cup子组件
<template>
<div>
<slot name="size" :msg="msg"></slot >
</div>
</template>
<script>
export default {
data(){
return{
msg:'300mL大小的杯子'
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
当为独占默认插槽时,v-solt可以省略default不写
注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确下面是官方的例子
<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
1
2
3
4
5
6
7
所以当出现多个插槽的时候,请使用完整的基于template 的语法
解构props的写法
这里使用上面cup组件的例子
<template>
<div>
<cup>
<template v-slot:default="{msg}"> //解构
<div>
{{msg}}
</div>
</template>
</cup>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
v-slot 的解构还提供 重命名的写法
<template>
<div>
<cup>
<template v-slot:default="{msg : size}"> //别名
<div>
{{size}}
</div>
</template>
</cup>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
动态插槽名
v-slot 支持2.6的动态参数写法
<layout>
<template v-slot:[attributeName]>
...
</template>
</layout>
1
2
3
4
5
这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data property attributeName,其值为 "header",那么这个绑定将等价于 v-slot:header。
插槽的缩写
2.6后插槽 可以把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header
v-slot:后面必须有值,不可写成#="{data}"
<template>
<div>
<cup>
<template #default="msg">
<div>
{{size}}
</div>
</template>
</cup>
</div>
</template>
————————————————
原文链接:https://blog.csdn.net/marendu/article/details/106288627.
http://go.ly.com/travels/member/person.html?uid=4437f32e775356e18047afb4e7d38441
https://www.sonystyle.com.cn/mysony/bbs/web/details/7563
http://user.ipathology.cn/90980
标签:slot,vue,作用域,插槽,默认,组件,scope,solt 来源: https://www.cnblogs.com/dasdfdfecvcx/p/12952940.html