vue插槽slot

1.匿名插槽

它容许你像这样合成组件:url

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

 而后你在 <navigation-link> 的模板中可能会写为:spa

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

当组件渲染的时候,这个 <slot> 元素将会被替换为“Your Profile”。插槽内能够包含任何模板代码,包括 HTML:code

<navigation-link url="/profile">
  <!-- 添加一个 Font Awesome 图标 -->
  <span class="fa fa-user"></span>
  Your Profile
</navigation-link>

甚至其它的组件:对象

<navigation-link url="/profile">
  <!-- 添加一个图标的组件 -->
  <font-awesome-icon name="user"></font-awesome-icon>
  Your Profile
</navigation-link>

若是 <navigation-link> 没有包含一个 <slot> 元素,则任何传入它的内容都会被抛弃。作用域

2.具名插槽

有些时候咱们须要多个插槽。例如,一个假设的 <base-layout> 组件的模板以下:it

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

对于这样的状况,<slot> 元素有一个特殊的特性:name。这个特性能够用来定义额外的插槽:io

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

在向具名插槽提供内容的时候,咱们能够在一个父组件的 <template> 元素上使用 slot 特性:table

<base-layout>
  <template 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 slot="footer">
    <p>Here's some contact info</p>
  </template>
</base-layout>

另外一种 slot 特性的用法是直接用在一个普通的元素上:模板

<base-layout>
  <h1 slot="header">Here might be a page title</h1>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <p slot="footer">Here's some contact info</p>
</base-layout>

咱们仍是能够保留一个未命名插槽,这个插槽是默认插槽,也就是说它会做为全部未匹配到插槽的内容的统一出口。上述两个示例渲染出来的 HTML 都将会是:class

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

3.插槽的默认内容

有的时候为插槽提供默认的内容是颇有用的。例如,一个 <submit-button> 组件可能但愿这个按钮的默认内容是“Submit”,可是同时容许用户覆写为“Save”、“Upload”或别的内容。

你能够在组件模板里的 <slot> 标签内部指定默认的内容来作到这一点。

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

若是父组件为这个插槽提供了内容,则默认的内容会被替换掉。

4.做用域插槽

有的时候你但愿提供的组件带有一个可从子组件获取数据的可复用的插槽。例如一个简单的 <todo-list> 组件的模板可能包含了以下代码:

<ul>
  <li
    v-for="todo in todos"
    v-bind:key="todo.id">
    {{ todo.text }}
  </li>
</ul>

可是在咱们应用的某些部分,咱们但愿每一个独立的待办项渲染出和 todo.text 不太同样的东西。这也是做用域插槽的用武之地。

为了让这个特性成为可能,你须要作的所有事情就是将待办项内容包裹在一个 <slot> 元素上,而后将全部和其上下文相关的数据传递给这个插槽:在这个例子中,这个数据是 todo 对象:

<ul>
  <li
    v-for="todo in todos"
    v-bind:key="todo.id"
  >
    <!-- 咱们为每一个 todo 准备了一个插槽,-->
    <!-- 将 `todo` 对象做为一个插槽的 prop 传入。-->
    <slot v-bind:todo="todo">
      <!-- 回退的内容 -->
      {{ todo.text }}
    </slot>
  </li>
</ul>

如今当咱们使用 <todo-list> 组件的时候,咱们能够选择为待办项定义一个不同的 <template> 做为替代方案,而且能够经过 slot-scope 特性从子组件获取数据:

<todo-list v-bind:todos="todos">
  <!-- 将 `slotProps` 定义为插槽做用域的名字 -->
  <template slot-scope="slotProps">
    <!-- 为待办项自定义一个模板,-->
    <!-- 经过 `slotProps` 定制每一个待办项。-->
    <span v-if="slotProps.todo.isComplete">✓</span>
    {{ slotProps.todo.text }}
  </template>
</todo-list>

在 2.5.0 以前,slot-scope 被命名为 scope 且被限制只能在 <template> 元素上使用。从 2.5.0 开始,slot-scope 再也不具备这些限制,而能够用在插槽内的任何元素或组件上。