插槽介绍
- 插槽是Vue实现了一套内容分发的API。
<slot>
元素:<slot>
元素作为承载内容分发的出口- 当组件渲染的时候,
<slot></slot>
元素将会替换为你所插入的内容(可以是字符串、HTML、组件)
字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<hello-word>
世界
</hello-word>
</div>
<!-- 组件 -->
<template id='hello'>
<div>
<span>你好!</span>
<slot></slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const HelloWord = {
template: '#hello'
}
new Vue({
el: '#app',
components: {
HelloWord
}
})
</script>
</body>
</html>
HTML
<body>
<div id="app">
<hello-word>
<h1>世界</h1>
</hello-word>
</div>
<template id='hello'>
<div>
<span>你好!</span>
<slot></slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const HelloWord = {
template: '#hello'
}
new Vue({
el: '#app',
components: {
HelloWord
}
})
</script>
</body>
组件
<body>
<div id="app">
<hello-word>
<demo-scope></demo-scope>
</hello-word>
</div>
<!-- 组件 -->
<template id='hello'>
<div>
<span>你好!</span>
<slot></slot>
</div>
</template>
<!-- 组件 -->
<template id='scope'>
<div>
你的名字是?
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const HelloWord = {
template: '#hello'
}
const DemoScope = {
template: '#scope'
}
new Vue({
el: '#app',
components: {
HelloWord,
DemoScope
}
})
</script>
</body>
注意⚠️:如果没有<slot></slot>
元素,那么组件起始标签到结束标签之间的任何内容都将会被抛弃。
具名插槽
v-slot
指令自Vue2.6.0起引入,提供更好的slot
和slot-scope
特性的API代替方案
- 一个不带
name
的<slot>
元素会带有隐含的名字‘default’ - 在向具名插槽提供内容的时候,我们可以在一个
<template>
元素上使用v-slot
指令,并以v-slot
的参数的形式提供其名称
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<hello-word>
<!-- 现在<template>元素的所有内容都将会被传入相应的插槽 -->
<template v-slot:header>
<div>头部</div>
</template>
<!-- 任何没有被包裹在带有v-slot的template元素中的内容都将会被视为默认插槽的内容 -->
<div>主体</div>
<template v-slot:footer>
<div>底部</div>
</template>
</hello-word>
</div>
<template id='hello'>
<div>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const HelloWord = {
template: '#hello'
}
new Vue({
el: '#app',
components: {
HelloWord
}
})
</script>
</body>
</html>
作用域插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 子组件使用 -->
<hello-word>
<template v-slot:header="scope">
<div>{{scope.user.first}}</div>
</template>
<div>主体</div>
<template v-slot:footer>
<div>底部</div>
</template>
</hello-word>
</div>
<template id='hello'>
<div>
<slot name="header" :user="msg"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 子组件
const HelloWord = {
template: '#hello',
data () {
return {
msg: {
first: '你好!世界。。。',
last: '你好!地球。。。'
}
}
}
}
new Vue({
el: '#app',
components: {
HelloWord
}
})
</script>
</body>
</html>
作用域插槽理解:
- 首先需要理解,上面的代码存在两个不同的作用域。一个是使用
HelloWord
组件所具有的Vue实例与对应的作用域,另一个则是HelloWord
这个组件自身对应的Vue实例与对应作用域 - 其次要知道这两个作用域是彼此隔离的,再不加任何额外设置的情况下,无法访问到彼此Vue实例,因此不要说什么
data
、methods
之类的Vue实例所具有的成员统统都无法交互的。 - 正是在此基础上,当我们需要达成这两个作用域能彼此知晓一些信息的目标时,不得不采取一些设置。这设置里就包括了作用域插槽。
- 同时这两作用域可以认为存在父子关系,即使用
HelloWord
组件的Vue作用域是父作用域,组件HelloWord
的Vue作用域是子作用域。进一步,我们可以将目标分成两大类:父知晓子的信息、子知晓父的信息。 - 所以作用域插槽的真正目的是让父知晓子的信息
什么是插槽prop
官方文档有这么一句话解释得很清楚:绑定在<slot>
元素上的特性被称为插槽prop。对应上面代码:user="msg"
就是插槽prop
结构插槽prop
<hello-word>
<template v-slot:header="{ user }">
<div>{{ user.first }}</div>
</template>
<div>主体</div>
<template v-slot:footer>
<div>底部</div>
</template>
</hello-word>
prop重命名
<hello-word>
<template v-slot:header="{ user: person }">
<div>{{ person.first }}</div>
</template>
<div>主体</div>
<template v-slot:footer>
<div>底部</div>
</template>
</hello-word>
插槽总结
- 插槽的内容可以是任何模版(字符串、HTML、组件)
- 2.6.0新增具名插槽,通过
<slot>
的name属性和v-slot
可以实现插槽的按需加载和指定位置加载 - 注意⚠️:
v-slot
指令是需要写在<template>
标签上的,v-slot
可以简写为(#) - 插槽可以简单的理解为:在子组件挖一个坑,坑里放什么东西由父组件来决定
- 作用域插槽的作用就是让父知晓子的信息
v-slot
可以简写为(#)x`