可以先阅读组件基础-简单了解通过插槽分发内容。
一、插槽定义
插槽将子组件标签间的内容分发到子组件模板的<slot>
标签位置。
如果没有<slot>
标签,那么该内容将被丢弃。
二、编译作用域
内容在哪个作用域编译,就可以访问哪个作用域的数据。
1.父级模板的作用域
在父组件的模板中定义的变量,可以在整个父组件的模板中访问,包括子组件中的插槽内容。
例如,我们在父组件中定义一个变量url
,在子组件插槽内容中访问:
<template>
<div>
<navigation-link url="./index">
This URL is {{url}}
</navigation-link>
</div>
</template>
2.子级模板的作用域
在子组件中定义的数据和变量,只能在子组件中访问,而不能在父组件中访问。
三、后备内容
插槽的后备内容即没有提供内容时的默认内容。
定义方式很简单:
<slot>Slot的默认内容</slot>
四、具名插槽
顾名思义:具有名字的插槽。
你可以为插槽指定名称name
,以便将内容分发到特定的插槽中。
接着,通过在template
元素上使用v-slot:插槽名参数
指令使用具名插槽:
完整示例:
<!DOCTYPE html>
<html>
<head>
<title>Vue 2 具名插槽 Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-layout>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<template v-slot:header>
<h1>这里可能是一个页面标题</h1>
</template>
<template v-slot:footer>
<p>这里是一些联系信息</p>
</template>
</my-layout>
</div>
<script>
Vue.component('my-layout',{
template:`
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<!--默认插槽,隐含name为`default`-->
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
`
})
var vm = new Vue({
el: '#app',
});
</script>
</body>
</html>
虽然我们故意将默认插槽的内容放在了名为header
的代码前面,但是结果依然按照插槽原本的顺序排列。
动态插槽名
我们可以使用动态参数绑定插槽名。
<template v-slot:[dynamicSlotName]></template>
具名插槽的缩写
v-slot
指令也有缩写,即使用#
替代v-slot:
,这样做我们就必须明确给出其插槽名称。
五、作用域插槽
作用域插槽这个概念是指让插槽内容能够访问子组件中才有的数据。
我们只需给<slot>
绑定prop,然后使用v-slot的值访问该prop
。v-slot的值实际上是所有绑定的prop的集合。
上例子:
<!DOCTYPE html>
<html>
<head>
<title>Vue 2 作用域插槽 Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-component>
<template v-slot="slotProps">
<p>{{slotProps.text}}</p>
</template>
</my-component>
</div>
<script>
Vue.component('my-component', {
template: `
<div>
<slot text="hello"></slot>
</div>
`
})
var vm = new Vue({
el: '#app',
});
</script>
</body>
</html>
注意,上面例子中我们v-slot
指令没有带参数,实际上它默认带了个default
参数,如果存在别的具名插槽,那么我就必须为v-slot
指令带上参数。
通过作用域插槽的机制,我们可以实现父组件控制插槽内容来控制子组件渲染不同的结果。
额外的不相关话题:使用
v-bind
指令时,什么时候加:
?私以为:这取决于v-bind绑定的属性的值,其值为静态字符串,不加
:
,其值若为变量或对象字面量,则加:
。
解构插槽prop
事实上,插槽内容会被封装在一个函数内,v-slot
的值就是其参数。
作为函数参数,我们可以使用JavaScript的解构语法,这会使得代码更简洁。
1.普通解构
<template v-slot="{text}">
<p>{{text}}</p>
</template>
2.重命名prop
<template v-slot="{text:msg}">
<p>{{msg}}</p>
</template>
3.指定后备内容
<template v-slot="{text={msg:'Hello'}}">
<p>{{text.msg}}</p>
</template>