Vue slot:作用域插槽、具名插槽的缩写

tags: Vuejs

作用域插槽

<slot> 内容在父模板编译,基於 Vue 的定义,在父模板中编译的内容访问 parent scope,在子模板中编译的内容访问 child scope,我们不能使用插槽内容访问 child scopeproperty

例如来说,我有一个子组件内容如下:

Vue.component('my-component', {
  data() {
    return {
      user: {
        name: 'Tony',
        nickname: 'TT',
        age: 23,
        born: 1999
      },
    }
  },
  template: `<div>
  <h2>name:<slot name="name">{{ user.nickname }}</slot></h2>
  <p>age:<slot name="age">{{ user.age }}</slot></p>
</div>`,
})

假如今天父组件想将 user.nickname 更改为呈现子组件中的 user.name ,如下方程序码:

const vm = new Vue({
  el: '#app',
  data: {},
  template: `
  <div id="app">
    <my-component>
      <template v-slot:name>{{ user.name }}</template>
      <template v-slot:age>{{ user.born }}</template>
    </my-copmonent>
  </div>`,
})

不出意外的,由於该处不能访问 child scope,Vue 将会给你满江红,和你说 user 是未定义的。

这是由於 user 位於子组件中,下方 Vue devtools 显示了 rootmy-component instance 各自的数据,在各自的模板中可以访问各自实体的数据。

若是想要在插槽中使用 child scope 中的数据,Vue 提供了一种方式,作用域插槽,透过该方式便可以使插槽使用子组件数据。

使用作用域插槽

如果想要使用插槽访问 child scope 的内容,可以使用 slot Prop ,将想要给插槽访问的 child scope 数据透过 v-bind 绑定在 <slot> 中,此时父组件的 插槽 便可以访问该数据:

要使用作用域插槽,透过以下步骤:

  1. 在子组件插槽使用 v-bind 绑定插槽 prop
  2. 父组件使用 v-slot:插槽名称="插槽 prop 名称" 定义插槽 prop 名称。(没有给予插槽名称时为 default,但使用多个插槽建议一律使用有参数的 v-slot
Vue.component('my-component', {
  data() {
    return {
      user: {
        name: 'Tony',
        nickname: 'TT',
        age: 23,
        born: 1999
      },
    }
  },
  template: `<div>
  <h2>name:<slot name="name" v-bind:user="user">{{ user.nickname }}</slot></h2>
  <p>age:<slot name="age" v-bind:user="user">{{ user.age }}</slot></p>
</div>`,
})
const vm = new Vue({
  el: '#app',
  template: `
  <div id="app">
    <my-component>
      <template v-slot:name="slotProp">{{ slotProp.user.name }}</template>
      <template v-slot:age="otherSlotProp">{{ otherSlotProp.user.born }}</template>
    </my-component>
  </div>`,
})

上方的插槽 prop 由於本身在 Vue 中的作用原理如下:

function (slotProp) { ... }

所以我们可以使用解构的方式简化程序码:

<my-component>
  <template v-slot:name="{ user }">{{ user.name }}</template>
  <template v-slot:age="{ user }">{{ user.born }}</template>
</my-component>

运用解构语法更可以支持我们重命名:

<my-component>
  <template v-slot:name="{ user: person }">{{ person.name }}</template>
  <template v-slot:age="{ user: person }">{{ person.born }}</template>
</my-component>

或是定义默认内容,适用於没有 slotProp 的情况:

<my-component>
  <template v-slot:name="{ user: { name: 'Ady'} }">{{ user.name }}</template>
  <template v-slot:age="{ user: { born: 1992 } }">{{ user.born }}</template>
</my-component>

动态 slot 名称

v-slot 也支持动态参数名称:

<my-component>
  <template v-slot:[name]="{ user: { name: 'Ady'} }">{{ user.name }}</template>
  <template v-slot:[age]="{ user: { born: 1992 } }">{{ user.born }}</template>
</my-component>

具名插槽的缩写

插槽也有缩写语法,只适用於 具名 插槽,写法很简单,只需要将 v-slot 取代成 #

<my-component>
  <template v-slot:name="{ user: { name: 'Ady'} }">{{ user.name }}</template>
  <template v-slot:age="{ user: { born: 1992 } }">{{ user.born }}</template>
</my-component>

可以简化为:

<my-component>
  <template #name="{ user: { name: 'Ady'} }">{{ user.name }}</template>
  <template #age="{ user: { born: 1992 } }">{{ user.born }}</template>
</my-component>

以上为此次内容,感谢看到这里的你,我们明天见。


若是文中有任何错误、错字、想讨论的内容,欢迎各位大大不吝鞭笞指正、交流分享,笔者不慎感激 ✦ ✦ ✦

▶︎ 笔者 github:https://github.com/YUN-RU-TSENG
▶︎ 老王卖瓜之笔者另一篇铁人:每天来点 CSS Specification

▶︎ 倘若不断向深处扎根,似乎就能茁壮成长 - RM


参考资料:

  1. Vuejs.org 2.x

<<:  [Day28] Go Bot使用者注册

>>:  Day29:每天一个小练习 - JS30-14-JS Reference VS Copy

[Day 19] 实作 - 介面篇3

首先先将各个快捷键设好 将ActionBattle_Var.js改成 开一只程序ActionBatt...

【Day 27】指标的范例讲解

今天,我们就来看一个指标的范例,测试一下对於指标的概念,是不是真的熟悉~ 看一下下面的程序码: #i...

Day13-JDK堆内存快照工具-jmap(三)自动导出内存映像文件

前言 接续着上篇,这篇要说明的是如何自动导出hprof文件,针对自动导出又有分两种状况:已是运行中的...

【Day 07】开始谈论主程序啦!!!

某一天我们提到,主要的逻辑都写在 django_chatbot/views.py。 但是里面牵涉太多...

python ModuleNotFoundError

python中引用不同文件夹下面的函数的时候,使用了__init__.py依然没有用,後来发现原因:...