因为在2.6.0中,具名插槽 和 作用域插槽 引入了一个新的统一的语法 (即v-slot 指令)。它取代了 slot 和 slot-scope,并且现在网上都说的是一些老版本的内容,官方文档不太容易理解,所以就整理了一篇有关于插槽(slot)使用的文章
Slot 通俗的理解就是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置)
并且可以作为承载分发内容的出口
内容插槽
定义两个组件 home.vue、test.vue
然后在home.vue组件中引用test.vue组件
插槽内可以包含普通文本
//home.vue
Hello Word
//test.vue
当组件渲染的时候,
插槽内也可以包含任何模板代码,包括HTML
在你的index.html引入Font Awesome图标的样式就直接可以用那里面的图标了
//home.vue
Hello Word
插槽内添加其他组件
//home.vue
Hello Word
如果
在插槽中使用数据
插槽跟模板其他地方一样都可以访问相同的实例属性(也就是相同的"作用域"),而不能访问
//home.vue
//插槽可以获取到home组件里的内容
Hello {{enhavo}}
data(){
return{
enhavo:'word'
}
}
//home.vue
//这里是获取不到name的,因为这个值是传给的
Hello {{name}}
规则:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
后备内容(默认内容)插槽
有时候我们需要给插槽设置一个具体的默认内容,当别的组件没有给你内容的时候,那么默认的内容就会被渲染
//test.vue
//在slot插槽里设置默认内容 Submit
在home.vue里直接使用test.vue如下:
//home.vue
那么最后设置的默认内容 Submit 将会被渲染
假如我们提供内容呢?
//home.vue
按钮
那么这个提供的内容将会替代默认的内容被渲染出来
具名插槽
有时候我们一个组件里需要多个插槽
那么怎么办呢? 对于这样的情况,
这时候,我们就可以使用name属性
如果一个
在向具名插槽提供内容的时候,我们可以在元素上使用v-slot指令,并以参数的形式提供其名称
Here might be a page title
A paragraph for the main content.
And another one.
Here some contact info
现在 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 中的内容都会被视为默认插槽的内容。
如果你希望更明确一点的话,那就把主体内容那个插槽里设置name="default",然后把上面的内容包裹起来
A paragraph for the main content.
And another one.
注:v-slot只能添加在一个上,(只有一种例外情况,下面会说)
作用域插槽
上面已经说了,插槽跟模板其他地方一样都可以访问相同的实例属性(也就是相同的"作用域"),而不能访问
那如果想访问
我们把需要传递的内容绑到
//test.vue
{{user.lastName}}
//定义内容
data(){
return{
user:{
firstName:"Fan",
lastName:"Jun"
}
}
}
然后在home.vue中接收传过来的值:
//home.vue
{{slotProps.usertext.firstName}}
这样就可以获得test.vue组件传过来的值了
绑定在
独占默认插槽的缩写语法
在上述情况下,当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上
这样写法还可以更简单,因为不带参数的v-slot就被假定为默认插槽,所以上面的代码还可以简化:
{{slotProps.usertext.firstName}}
注: 默认插槽 的缩写语法不能和 具名插槽 混用,因为它会导致作用域不明确
{{slotProps.usertext.firstName}}
slotProps is NOT available here
只要出现多个插槽,始终要为所有的插槽使用完整的基于的语法:
{{ slotProps.user.firstName }}
...
解构插槽Prop
因为 作用域插槽 的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里
这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JS 表达式
所以本来是这样写的:
{{slotProps.usertext.firstName}}
还可以这样写:
{{usertext.firstName}}
这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,
例如可以将 usertext 重命名为 person:
{{person.firstName}}
甚至可以定义 后备内容(默认内容),用于插槽没有值时可以使用默认内容的情形:
{{usertext.firstName}}
动态插槽名(2.6.0新增)
动态指令参数(需要自己了解)也可以用在v-slot上,来定义动态的插槽名:
...
具名插槽的缩写(2.6.0新增)
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:
原来是这样写的:
Here might be a page title
A paragraph for the main content.
And another one.
Here some contact info
现在可以这样写:
Here might be a page title
A paragraph for the main content.
And another one.
Here some contact info
注:该指令和其他指令一样,只在其有参数的时候才可用
下面的书写形式是错误的:
{{ usertext.firstName }}
如果希望使用缩写的话,必须始终以明确插槽名取而代之:
{{ usertext.firstName }}
其他示例
插槽 prop 允许我们将插槽转换为可复用的模板,这些模板可以基于输入的 prop 渲染出不同的内容。 这在设计封装数据逻辑同时允许父级组件自定义部分布局的可复用组件时是最有用的。
例如,我们要实现一个
-
{{ todo.text }}
我们可以将每个 todo 作为父级组件的插槽,以此通过父级组件对其进行控制,然后将 todo 作为一个插槽 prop 进行绑定:
-
{{ todo.text }}
现在当我们使用
✓
{{ todo.text }}
至于那些废弃了的 slot 和 slot-scope 特性,这里就不在阐述了,如果有兴趣了解的话,请参考官方文档