插槽内容
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">
<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>Submitslot>
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 titleh1>
template>
<p>A paragraph for the main content.p>
<p>And another one.p>
<template slot="footer">
<p>Here's some contact infop>
template>
base-layout>
另一种slot特性的用法是直接用在一个普通的元素上:
<base-layout>
<h1 slot="header">Here might be a page titleh1>
<p>A paragraph for the main content.p>
<p>And another one.p>
<p slot="footer">Here's some contact infop>
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是不会工作的。牢记一条准则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在自己作用域内编译