一、定义:
基础定义
如果被引用的子组件里面包含 <slot></slot>
,那么当它实际被使用的时候,<slot></slot>
会被替换成使用时开始标签和结束标签之间的值。
<!-- 父组件 -->
<navigation-link url="/profile">
Your Profile
</navigation-link>
<!-- 子组件 -->
<a v-bind:href="url" class="nav-link">
<slot></slot>
</a>
默认值
子组件在 <slot></slot>
标签内部写值,则为默认值,会在父组件无传值时使用。
<!-- 子组件 -->
<a v-bind:href="url" class="nav-link">
<slot>我是默认值</slot>
</a>
<!-- 父组件 -->
<navigation-link url="/profile">
我是更新后的值
</navigation-link>
具名插槽
父组件中 v-slot:name
包裹元素,子组件使用 <slot name="name"></slot>
接收元素,就可以把父组件中的特定元素传送到子组件的特定部分。
如果没有用 v-slot:name
包裹,那么会默认name为 default
,同理子组件中的slot的name属性也是 default
<!-- 子组件 -->
<div id="TestSlot">
<slot name="one" />
<slot name="two" />
</div>
<!-- 父组件 -->
<test-slot>
<template v-slot:two>
<div>我是第二个插槽</div>
</template>
<template v-slot:one>
<div>我是第一个插槽</div>
</template>
</test-slot>
<!-- 渲染结果 -->
<div data-v-725483ce="" data-v-15737ea2="" id="TestSlot">
<div data-v-15737ea2="" data-v-725483ce="">我是第一个插槽</div>
<div data-v-15737ea2="" data-v-725483ce="">我是第二个插槽</div>
</div>
具名插槽的缩写(>2.6.0)
v-slot:top
可以被缩写为 #top
,该语法在名字为空时无效,至少要使用#default
作用域插槽
在vue的组件中,父组件不能访问子组件中的数据。
<!-- 子组件 -->
<template>
<div>
<slot name="top" :myUser="user">{{user.currentName}}</slot>
</div>
</template>
<script>
export default {
name: "TestSlot",
data: function () {
return {
user: {currentName: "Ross", lastName: 'Foo'}
}
}
}
</script>
<!-- 父组件 -->
<test-slot v-slot:top>{{user.lastName}}</test-slot>
<!-- 报错 -->
如果想要父组件访问子组件中的数据,只需要加上scope的传值,就可以拿到在slot上传入的所有属性:
<!-- 子组件 -->
<template>
<div>
<slot name="top" :myUser="user" :testUser="'testUser'"></slot>
</div>
</template>
<script>
export default {
name: "TestSlot",
data: function () {
return {
user: {currentName: "Ross", lastName: 'Foo'}
}
}
}
</script>
<!-- 父组件 -->
<test-slot v-slot:top="scope">{{scope}}</test-slot>
<!-- { "myUser": { "currentName": "Ross", "lastName": "Foo" }, "testUser": "testUser" } -->
与解构赋值结合
// 与上例结合
<!-- 父组件 -->
<test-slot v-slot:top="{myUser}">{{myUser}}</test-slot>
<!-- { "currentName": "Ross", "lastName": "Foo" } -->
「已废弃」作用域插槽slot-scope和slot
注意!与
v-slot
相比,slot-scope
必须要在组件使用的内部新建一个节点,<template>
或者<div>
都可以。
官方文档是这么写的,应该是单指的默认值插槽的使用,毕竟具名插槽还是要在父组件里新增节点。
<test-slot>
<template slot="top" slot-scope="slotProps">
{{slotProps}}
</template>
</test-slot>
二、为什么要用
如果单纯使用 $emit
和 props
进行父子组件的交互,例如 根据子组件中某个交互决定整体组件显隐性的变化这样的需求,就需要冗杂至少一个方法一个变量。
官网的例子就很直接:
<todo-list v-bind:todos="todos">
<template v-slot:todo="{ todo }">
<span v-if="todo.isComplete">✓</span>
{{ todo.text }}
</template>
</todo-list>
20.05.27 updated
- 🤔在这种场景下,使用slot似乎不如.sync