本次尝试一下,将知识讲给别人听的学习方法。
什么是插槽
我们在引用组件时想要对组件样式作出一些修改,这种情况比较适合使用插槽,否则不得不再写一个代码重复度高的组件或者将各种代码都塞到一个组件中。
插槽简单示例
我们引用组件,在标签内写入一些html代码
<navigation-link url="/profile">
Your Profile
</navigation-link>
正常情况下这样只会引用组件,标签内的内容不会被渲染。
我们需要在组件中添加一个标签"slot",这个标签渲染后将被替换为在父组件引用子组件的标签中的代码。如下:
<template>
<a v-bind:href="url" class="nav-link" >
<slot></slot>
</a>
</template>
渲染为
<a v-bind:href="url" class="nav-link" >
Your Profile
</a>
插槽的编译作用域(数据的调用范围)
插槽中的代码在正常情况下只能访问所在实例的数据,而不能访问要调用的组件中的数据。
<navigation-link url="/profile">
Logged in as {{ user.name }}
</navigation-link>
本例中只能访问组件引用标签所在实例中的user,若没有则为undefined
后备内容
"slot"标签内可以写html代码,当插槽内没有内容时会将"slot"标签内的代码渲染,否则不会渲染。
具名插槽
我们有时需要将引用组件的标签中不同的代码放在组件中不同的位置,这时候就要分别给插槽中代码和slot标签都命名。
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
slot有一个属性name可以用来给slote命名
<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用来定义想要将代码添加到组件的哪一个slot中(将代码用template括起来)。
注意:一般v-slot只能放在template标签上,当组件标签中的代码只提供给默认插槽时,可以在组件标签上使用。
补充:
所有未被特殊命名的内容都会被归为默认插槽,默认插槽也有名子,即v-slot:default。
一个不带 name 的slot会默认带上default。
测试发现当给template用v-slot:default时,未被匹配的代码不会再提供给默认slot,用slot="default"时,则未被匹配的仍被渲染。
作用域插槽
有时我们需要让组件引用标签中的代码访问组件中的数据,即父组件访问子组件的数据。
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
如上,在子组件中的slote标签上用v-bind来绑定要传输的数据。
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在父级作用域中,v-slot:default="slotProps"这样的格式来获取子组件中传输的数据。获取的属性都将作为slotProps的属性被访问。
只有默认插槽的缩写语法
当只有默认插槽时,可以直接用v-slot=“slotProps”(直接添加在组件引用标签上)来接收数据。
注意:这样的写法不能与具名插槽混用。
解构插槽
可以用解构赋值的方法接收指定的数据,如获取user
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
也可以重命名
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{{ user.firstName }}
</current-user>
缩写
v-slot:head = #head
废弃语法
具名插槽
<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>
在template上使用slot,用以指定代码要传给那个插槽,
与v-slot不同的是,slot可以用在普通html元素上。
作用域插槽slot-scope
同样用于父作用域调用子组件数据的情况。
<slot-example>
<template slot-scope="slotProps">
{{ slotProps.msg }}
</template>
</slot-example>
与v-slot:="slotProps"不同的是,slot-scope="slotProps"可以写在非template元素上。