Vue3 中插槽(slot)的用法
概要
Vue3(其实从2.6开始)中引入了一个新的指令v-slot,用来表示具名插槽和默认插槽
基础示例
{{ msg }}
{{ msg }}
为什么要这么做
在v2.5中介绍了slot-scope,可以直接在插槽元素上使用。
{{ msg }}
同样的,我们也可以在组件上这样使用。
{{ msg }}
然而,上面的示例会导致一个问题:slot-scope的位置不能清晰的反映出这个作用域变量是哪一个 组件提供的。上面例子中slot-scope是写在组件上,但是实际上这个作用域变量的定义是有组件的默认插槽提供的。
当嵌套的层级越深,情况就会变得越糟。
{{ foo }} {{ bar }} {{ baz }}
像上面这种情况,我们无法立即分辨出模板上作用域变量是由那一个组件提供的。
细节设计
引入一个新的指令v-slot
我们可以在slot容器上使用v-slot来表示一个传入组件的插槽,通过指令参数来表示插槽的名称。
作用域插槽的内部工作原理是将插槽的内容包裹在一个函数里
function(slotProps){
// 插槽内容
}
这就意味着v-slot的值实际上可以是任何能够作为函数定义中的参数的Javascript表达式,所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:
Message from header slot: {{ msg }}
v-slot可以直接用在组件上,如果没有参数,则表示默认的作用域插槽,传递给默认插槽的属性应该作为变量在其属性值声明。
{{ msg }}
新旧语法对比
-
对于常用的场景(只有一个默认的作用域插槽)
{{msg}} -
作用域变量与组件之间的联系更加的清晰
{{ foo }} {{ bar }} {{ baz }}使用新语法也可以达到同样的效果
{{ foo }} {{ bar }} {{ baz }}
注意:组件提供的作用域变量依然声明在当前组件上,新的语法更清晰的展示出组件与作用域变量的关系。(父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。)
动态插槽名
动态指令参数也可以用在 v-slot 上,来定义动态的插槽名:
...
插槽指令的缩写
和 v-bind和v-on相似,缩写只有在存在参数时才生效,这就意味着v-slot没有参数时不能使用#=,对于默认插槽,可以使用#default来代替v-slot
Message from header: {{ msg }}
A static footer
Message from header: {{ msg }}
A static footer
{{ msg }}
{{ msg }}
更多的用例对比
默认的文本作用域插槽
{{ msg }}
{{ msg }}
默认的含DOM节点的插槽
{{msg}}
{{msg}}
嵌套的默认插槽
{{ foo }} {{ bar }} {{ baz }}
{{ foo }} {{ bar }} {{ baz }}
命名插槽
text slot: {{ msg }}
element slot: {{ msg }}
text slot:{{msg}}
element slot: {{msg}}
嵌套 & 命名 / 默认
{{ one }} {{ bar }}
{{ two }} {{ bar }}
{{ one }} {{ bar }}
{{ two }} {{ bar }}