插槽

一般情况下,html 中的组件之间的内容会被抛弃,例如:

vue3 template语法 vue template详解_作用域

效果:

vue3 template语法 vue template详解_插槽_02


对于这种情况,我们可以使用 <slot> 在 <box></box> 内添加内容:

vue3 template语法 vue template详解_作用域_03

效果:

vue3 template语法 vue template详解_vue_04

即:当组件渲染的时候,<slot></slot> 将会被替换为 "<p>content</p>",插槽内可以包含任何模板代码,即使是其他组件。


编译作用域

我们可以在插槽中访问来自 Vue 实例的 property:

vue3 template语法 vue template详解_vue_05

效果:

vue3 template语法 vue template详解_作用域_06


但是不能访问到组件的 prop:

vue3 template语法 vue template详解_vue3 template语法_07

效果:

vue3 template语法 vue template详解_模版_08

这里的 temp 是 undefined,因为该插槽内容是传递给 <box></box> 的,而不是在 <box></box> 组件的内部模板中定义的。

对此官方解释是:

父级模板里的所有内容都是在父级作用域中编译的,子模版里的所有内容都是在子作用域中编译的。


后备内容

后备内容也就是默认内容,类似于函数的默认参数,它只会在没有提供内容的时候被渲染,例如:

vue3 template语法 vue template详解_插槽_09

效果:

vue3 template语法 vue template详解_模版_10


如果提供内容则会取代后备内容:

vue3 template语法 vue template详解_作用域_11

效果:

vue3 template语法 vue template详解_vue3 template语法_12


具名插槽

默认情况下,<slot></slot> 会被替换为提供的全部内容,即提供的内容会视为默认插槽的内容:

vue3 template语法 vue template详解_插槽_13

效果:

vue3 template语法 vue template详解_vue3 template语法_14


但是我们可能希望将对应的内容放在对应的标签内,对此,<slot> 元素 name attribute 可以用来定义额外的插槽:

vue3 template语法 vue template详解_vue_15

一个不带 name 的 <slot> 会带有隐含的 name="default"

在向具名插槽提供内容时,可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

vue3 template语法 vue template详解_作用域_16

现在 <template> 元素中的所有内容都会被传入对应的插槽,任何没有包裹在带有 v-slot 指令的 <template> 中的内容都会视为默认插槽的内容(ps:v-slot 只能添加在 <template> 上,除非被提供的内容只有默认插槽时)。

效果:

vue3 template语法 vue template详解_vue_17


作用域插槽

默认情况下,插槽内容是不能访问到组件的 prop 的,对此,可以将组件的 prop 作为 <slot> 元素的一个 attribute 绑定上去:

vue3 template语法 vue template详解_vue_18

绑定在 <slot> 元素上的 attribute 被称为插槽 prop,现在在父级作用域中,可以使用带值的 v-slot 来定义插槽 prop 的名字:

vue3 template语法 vue template详解_模版_19

效果:

vue3 template语法 vue template详解_模版_20

v-slot:default="slotProps" 中的 slotProps 是可自主命名的。