Vue文档4 插槽

插槽

合成组件 里面可以包括HTML片段,其他组件等

<navigation-link url="/profile">
  Your Profile
</navigation-link>

组件写法

  v-bind:href="url"
  class="nav-link"
>
  <slot></slot>
</a>

编辑作用域

插槽中使用数据

<navigation-link url="/profile">
  Logged in as {{ user.name }}
</navigation-link>

该插槽跟模板的其它地方一样可以访问相同的实例 property

不能访问 <navigation-link> 的作用域,例如上面的 url 是访问不到的。

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


后备内容

等于默认渲染,它只会在没有提供内容的时候被渲染 ,例如在一个 <submit-button> 组件中

<button type="submit">
  <slot>Submit</slot>
</button>

现在当我在一个父级组件中使用 <submit-button> 并且不提供任何插槽内容时:

<submit-button></submit-button>

后备内容“Submit”将会被渲染:

<button type="submit">
  Submit
</button>

但如果提供内容就会替代插槽里面的后备内容

<submit-button>
  Save
</submit-button>


具名插槽

有时我们需要多个插槽

有时我们需要多个插槽。例如对于一个带有如下模板的 <base-layout> 组件:

<div class="container">
  <header>
    <!-- 我们希望把页头放这里 -->
  </header>
  <main>
    <!-- 我们希望把主要内容放这里 -->
  </main>
  <footer>
    <!-- 我们希望把页脚放这里 -->
  </footer>
</div>

<slot> 元素有一个特殊的 attribute:name

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

一个不带 name<slot> 出口会带有隐含的名字“default”。

我们可以在一个 <template> 元素上使用 v-slot 指令

<base-layout>  <template v-slot:header>    <h1>Here might be a page title</h1>  </template>  <p>A paragraph for the main content.</p>  <p>And another one.</p>  <template v-slot:footer>    <p>Here's some contact info</p>  </template></base-layout>

现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot<template> 中的内容都会被视为默认插槽的内容。

v-slot 只能添加在 <template>


作用域插槽

因为从父级传来的值在插槽子级是不可以直接访问的

<span>  <slot>{{ user.lastName }}</slot></span>

<current-user>  {{ user.firstName }}</current-user>

所以用到了插槽 prop

<span>  <slot v-bind:user="user">    {{ user.lastName }}  </slot></span>

v-slot 来定义我们提供的插槽 prop 的名字

<current-user>  <template v-slot:default="slotProps">    {{ slotProps.user.firstName }}  </template></current-user>

独占默认插槽的缩写语法

当只有默认插槽时候可以简写

<current-user v-slot="slotProps">  {{ slotProps.user.firstName }}</current-user>

只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template> 的语法:

<current-user>  <template v-slot:default="slotProps">    {{ slotProps.user.firstName }}  </template>  <template v-slot:other="otherSlotProps">    ...  </template></current-user>

解构插槽Prop

作用域插槽的内部工作原理是将你的插槽内容包裹在一个拥有单个参数的函数里:

使用 ES2015 解构来传入具体的插槽 prop

<current-user v-slot="{ user }">  {{ user.firstName }}</current-user>

动态插槽名

<base-layout>  <template v-slot:[dynamicSlotName]>    ...  </template></base-layout>

具名插槽的缩写

把参数之前的所有内容 (v-slot:) 替换为字符 #

例如 v-slot:header 可以被重写为 #header'