赞
踩
Vue在2.6.0中,更新添加了一个新的指令v-slot,用于取代原先的slot与slot-scope属性的功能。
注意:此处的slot为属性,不是HTML标签那个<slot></slot>
Vue中的插槽很好用也很实用,在实际开发项目时或多或少几乎都会遇到,很多第三方引入的组件提供的修改内容的方法,也是通过插槽。
但网上关于插槽的教程与介绍都还是 “插槽种类分为三种:单个插槽/具名插槽/作用域插槽” 等等,也包括很多第三方组件仍然使用着slot与slot-scope属性。
(例如下图便是element-ui关于el-tree组件的文档中介绍如何去自定义节点内容)
如果你对slot以及slot-scope属性还不理解,对插槽还不是很熟悉,推荐看一下这篇博文,博主对于vue中的插槽写的非常详尽易懂
虽然slot以及slot-scope属性已经被废弃,但在vue 2.x版本中未被移除,依然可以使用,特别是在很多基于Vue的框架中被大量使用,所以学习还是很有必要的!
<!--版本一:-->
<class>
<template slot-scope="name">
<div>
{{ name }}
</div>
</template>
</class>
<!--版本二:-->
<class>
<div slot-scope="name">
{{ name }}
</div>
</class>
<!--版本三:-->
<class>
<people slot-scope="name">
{{ name }}
</people>
</class>
这个用法很常用,几乎现在的插件都是这么写的,然而这样使用,有个大问题:
无法直观表示该slot-scope用于哪个组件的插槽,明明是写在<people>标签上,然而跟people组件没有关系,这个name竟然是class组件中的数据。
如果再套娃几层:
<class>
<people slot-scope="grade">
<book slot-scope="number">
<div slot-scope="name">
{{ grade }} {{ number }} {{ name }}
</div>
</book>
</people>
</class>
太模糊了,连官方自己都承认:
It’s not immediately clear which component is providing which variable in this template.
有人又提议,那既然这样有问题,那我们回到Vue 2.5之前,强制slot-scope使用在标签下不就行了:
加功能容易,改功能难,删功能更难!
毕竟那么多人已经用上这个语法了
当时学习插槽时,就被各种“单个插槽”、“具名插槽”、“作用域插槽”什么的弄得云里雾里,明明在子组件里都是<slot>框住的部分,功能都是提供给父组件一块可在父组件中定义的HTML块,它可以带子组件的数据也可以不带,可以带名字也可以不带名字使用默认的插槽,没必要特意去分成三种。
不过也是因为各种插槽一开始用法上区别还是蛮大的,最后因为不断更新成现在这种用法类似的样子
既然如此官方自然会希望统一插槽类型,不管他是不是作用域插槽和非作用域插槽,他们全都是插槽就行了。那无论是slot-scope甚至是slot这两个属性,都没有必要了。
在子组件中依然是使用<slot></slot>去设定你要在父组件中替换的位置,而在父组件中用v-slot写在对应子组件下标签上,使得标签下的内容插入插槽中。
设定每一个插槽都是作用域插槽,只要为v-slot设定属性值来声明接收到的数据。设定使用伪指令参数来设定插槽名称。
下面举个例子:
<class>
<template v-slot:slotName="grade">
<div>
{{ grade }}
</div>
</template
</class>
其中,:slotName表示使用名称为‘slotName’的插槽(即之前slot属性的作用),=“grade”声明接受到的子组件的数据(即之前slot-scope属性的作用)
若对于只有单个默认插槽的组件来说,父组件使用其插槽时可以简洁使用,例:
<foo v-slot="data">
{{ data }}
</foo>
可以看到相比之前slot-scope的简洁用法,v-slot这个用法使作用域与提供它的组件之间的联系更加清晰,v-slot在什么组件上就是指明什么组件的作用域。
让我们回头看我们的套娃例子使用v-slot有什么变化:
<class v-slot="grade">
<people v-slot="number">
<book v-slot="name">
<div>
{{ grade }} {{ number }} {{ name }}
</div>
</book>
</people>
</class>
现在就很清晰了,grade就是class组件的grade,number就是people组件的number,name就是book组件的name。
注意:只有单个默认插槽的组件可以使用这样的简洁语法
这里贴几个官方的新旧对比例子,方便大家理解:
1)默认插槽(填充文字)
<!-- 旧 -->
<foo>
<template slot-scope="{ msg }">
{{ msg }}
</template>
</foo>
<!-- 新 -->
<foo v-slot="{ msg }">
{{ msg }}
</foo>
2)默认插槽(填充元素)
<!-- 旧 -->
<foo>
<div slot-scope="{ msg }">
{{ msg }}
</div>
</foo>
<!-- 新 -->
<foo v-slot="{ msg }">
<div>
{{ msg }}
</div>
</foo>
3)嵌套的默认插槽
<!-- 旧 --> <foo> <bar slot-scope="foo"> <baz slot-scope="bar"> <template slot-scope="baz"> {{ foo }} {{ bar }} {{ baz }} </template> </baz> </bar> </foo> <!-- 新 --> <foo v-slot="foo"> <bar v-slot="bar"> <baz v-slot="baz"> {{ foo }} {{ bar }} {{ baz }} </baz> </bar> </foo>
4)具名插槽
<!-- 旧 --> <foo> <template slot="one" slot-scope="{ msg }"> text slot: {{ msg }} </template> <div slot="two" slot-scope="{ msg }"> element slot: {{ msg }} </div> </foo> <!-- 新 --> <foo> <template v-slot:one="{ msg }"> text slot: {{ msg }} </template> <template v-slot:two="{ msg }"> <div> element slot: {{ msg }} </div> </template> </foo>
5)混合使用
<!-- 旧 --> <foo> <bar slot="one" slot-scope="one"> <div slot-scope="bar"> {{ one }} {{ bar }} </div> </bar> <bar slot="two" slot-scope="two"> <div slot-scope="bar"> {{ two }} {{ bar }} </div> </bar> </foo> <!-- 新 --> <foo> <template v-slot:one="one"> <bar v-slot="bar"> <div>{{ one }} {{ bar }}</div> </bar> </template> <template v-slot:two="two"> <bar v-slot="bar"> <div>{{ two }} {{ bar }}</div> </bar> </template> </foo>
如果你使用的是Vue 2.x的版本,那么你仍然可以继续使用slot属性定义具名插槽,使用slot-scope属性定义作用域插槽,也可以使用新的v-slot(2.6版本之后)
然而如果你使用Vue 3.x的版本,那么你只能使用v-slot指令
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。