Vue--插槽

插槽内容

Vue实现了一套内容分发的API,这套API基于当前的Web Component规范草案,将slot元素作为承载分发内容的出口。

它允许你这样合成组件:

<navigation-link url='/profile'>
    You Profile
</navigation-link>

然后你在navigation-link的模板中可能会写:

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

当组件渲染的时候,这个slot元素将会被替换为“Your Profile”。插槽内可以包含任何的末班,包括HTML:

<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>

其实简单来说插槽就是在组件模板中留下一个位置,这样调用组件时,组件里包裹的内容,比如上例中的图标组件、“Your Profile”,就能在组件中找到位置,并在模板编译之后显示出来。

反之,如果没有了slot插槽,那么调用组件时包裹的内容就会被丢弃掉。

插槽的默认内容

调用组件的时候,组件传入了内容,这时如果没有slot插槽,内容会被丢弃,因为组件模板里没有给传入的内容预留位置。设想一下,反过来,在组件模板里设置了slot插槽,并给了它一个默认的内容,但是调用组件的时候,没有传内容过来,这样的话,呈现的页面会是怎样的呢?有预留位置,位置里有内容,但是调用的时候没有传新的内容进来,预留位置是在的,位置里有内容,所以我们能很容易的可以推论到,这个时候会显示slot插槽里的默认内容。

有时候为插槽提供默认的内容是很有用的。例如,一个submit-button组件可能希望这个按钮的默认内容是“Submit”,但是同时允许用户覆写“Save”、“Update”或别的内容,就可以在slot标签内部指定默认的内容来做到这一点。

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

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

具名插槽

有时候我们需要多个插槽。例如,一个假设的base-layout组件模板如下:

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

对于这样的情况,slot元素有一个特殊的属性:name。这个特性可以用来定义额外的插槽:

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

在向具名插槽提供内容的时候,我们可以在一个父组件的template元素上使用slot特性:

<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>

两种方法效果是一样的,但是这里有两个小问题需要注意一下:

1. 标签的语义化会影响插槽里的内容例如我们使用h1替换template之后,slot为header里的内容显示状态等同h1标签下的显示状态。

2. 非template标签下的slot插槽不能设置默认内容:也就是我们上面提到的插槽的默认内容这个功能是不可用的,就是设置了默认内容不会显示。

作用域插槽

当我们想在插槽内使用数据时,我们可以这么做:

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

该插槽可以访问跟这个模板的其它地方相同的实例属性(也就是说“作用域”是相同的),但这个插槽不能访问navigation-link的作用域。例如尝试访问url是不会工作的。牢记一条准则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在自己作用域内编译

猜你喜欢

转载自blog.csdn.net/DayDreamWMM/article/details/82761245