一、定义:
基础定义
如果被引用的子组件里面包含 <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
