在Vue的官方文档中,关于v-slot插槽的使用,介绍的不是非常清晰明确,插槽这个东西其实很好理解,当我们定义了一个Vue组件后,我们是不能在调用组件时在里面再定义其它的dom结构的:
<submit-button>
<div>Save</div>
</submit-button>
上述这种结构是不合法的,如果 submit-button组件里
没有包含一个 <slot>
标签,则该组件起始标签和结束标签之间的任何内容都不会被显示,会被抛弃。那如果我们想在组件中再嵌入其它的dom结构该怎么办呢,这个时候就可以用到插槽这个功能了。在react同样具备这个功能,只不过他不向Vue那样封的这么彻底,给你几个明明白白的属性供你去使用,而是更贴近原生:
<!-- HTML -->
<Range>
<Text>插槽</Text>
<Text>react native</Text>
</Range>
// JSX语法
export default class Range extends Component {
constructor(props) {
super(props)
}
render() {
return (
<View style={styles.body}>
{this.props.children}
</View>
)
}
在react中是通过this.props.children这个属性来拿到组件中定义的dom结构,并在组件中定义位置去渲染。看到react的这个示例后,对你了解Vue的插槽应该能起到一定的帮助。
简单的说,插槽就是让你能够在组件标签中再定义其它的DOM结构。
插槽内容
插槽内可以包含任何模板代码,包括 HTML或者其它组件:
<!-- 添加HTML内容 -->
<touch-bar>
<!-- 添加一个 Font Awesome 图标 -->
<span class="fa fa-user"></span>
点击这里
</touch-bar>
<!-- 添加其它组件 -->
<touch-bar>
<!-- 添加一个按钮的组件 -->
<touch-button name="user"></touch-button>
点击这里
</touch-bar>
编译作用域
在Vue当中,父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
<navigation-link url="/profile">
Logged in as {{ user.name }}
</navigation-link>
在上面代码中,该插槽跟模板的其它地方一样可以访问相同的实例属性 (也就是相同的“作用域”)user.name,而不能访问 <navigation-link>
的作用域。例如 url
是访问不到的:
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
</navigation-link>
这里的 `url` 会是 undefined,因为 "/profile" 是传递给<navigation-link>组件的而不是在 <navigation-link> 组件标签内部定义的。
插槽的默认内容
有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。例如在一个 <submit-button>
组件中,我们可能希望这个 <button>
内绝大多数情况下都渲染文本“Submit”。为了将“Submit”作为后备内容,我们可以将它放在 <slot>
标签内:
<button type="submit">
<slot>Submit</slot>
</button>
现在当我在一个父级组件中使用 <submit-button>
并且不提供任何插槽内容时,后备内容“Submit”将会被渲染,但是如果我们提供内容,则这个提供的内容将会被渲染从而取代后备内容:
<!-- 不提供内容 -->
<submit-button></submit-button>
<!-- 提供内容 -->
<submit-button>
Save
</submit-button>
具名插槽
有时我们在一个组件需要多个插槽,每个插槽被用在组件的不同的位置,对于这样的情况,<slot>
元素有一个特殊的特性:name,
这个特性可以用来定义额外的插槽的名称,一个不带 name
的 <slot>
会默认带有隐含的属性“default”:
<!-- 组件定义 -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
那么我们该如何使用呢?在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令,并以 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>
注意: v-slot
只能添加在一个 <template>
上
作用域插槽
有时让插槽内容能够访问子组件中才有的数据是很有用的,这就正好解决了上面所说的编译作用域的问题。例如,设想一个带有如下模板的 <current-user>
组件,我们想让它的后备内容显示用户的名,以取代正常情况下用户的姓,如下:
<!-- current-user组件定义 -->
<span>
<slot>{{ user.lastName }}</slot>
</span>
<!-- 使用current-user组件 -->
<current-user>
{{ user.firstName }}
</current-user>
上述代码不会正常工作,因为只有父级中 <current-user>
组件可以访问到 user.firstName
,我们提供的内容是在父级渲染的,所以在<current-user>组件中定义的插槽拿不到user.lastName
。
为了让 user
在父级的插槽内容中可用,我们可以将 user
作为 <slot>
元素的一个特性绑定上去,绑定在 <slot>
元素上的特性被称为插槽 prop。
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
在父级作用域中,我们还可以给<current-user>中的
v-slot
给定一个值来定义插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
以上就是关于Vue插槽的讲述!