目录
Vue中插槽(slot)的使用
源码 点击
- 插槽最基本的用法就是允许我们想一个组件中插入一些
html
代码 - 有了插槽我们便可以向组件标签内写
html
代码。
前提
-
我们可以使用
vue-cli
创建一个基本的vue项目,我们接下来一步一步去做 -
我是使用的
vue-cli
的默认快速生成一个项目,目录如下
1. 插槽的基本使用
- 在
components
文件夹下新建MySlots.vue
和MyProfile.vue
- 其中,
MySlots.vue
表示<slot>
所在的组件
- 其中,
- 写上如下代码
MyProfile.vue
<template>
<div>
<my-slots>
<span>i love you ,</span>
</my-slots>
</div>
</template>
<script>
import MySlots from '@/components/MySlots'
export default {
components: {
MySlots
}
};
</script>
MySlots.vue
<template>
<div>
<span>my dear , </span>
<slot></slot>
<span>i want to see you</span>
</div>
</template>
- 一定不要忘了在根组件引入我们的组件
说明
- 当组件被渲染的时候
<slot>
标签会被组件标签中的html
模板替换掉 - 也就是说
i love you
,会被插入到my dear,
和i want to see you
之间
结果
- 当我们运行项目后,观察浏览器
注意事项
- 插槽内的模板的取值,他是取得当前组件的值
我们在原来的基础上增加如下代码
MySlots.vue
data () {
return {
myDearName: "xxx"
}
},
MyProfile.vue
<template>
<div>
<my-slots>
<span> {{myDearName}}</span>
<span>i love you ,</span>
</my-slots>
</div>
</template>
<script>
import MySlots from '@/components/MySlots'
export default {
data() {
return {
myDearName: "yyy"
};
},
};
</script>
- 需要注意的是我们在两个组件中都增加了
myDearName
属性,只是所赋的值不同,我们观察一下他去哪个组件的值
- 我们发现他取得是
yyy
,也就是MyProfile
组件中的值,所以我们要记住这样一句话
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
2. 具有默认值的插槽
- 我们接着在
components
文件夹下新建DefaultSlots.vue
,表示具有默认值的插槽 - 我们写上如下结构
DefaultSlots.vue
<template>
<div>
<slot>Defalut content</slot>
</div>
</template>
- 接着,我们在
MyProfile.vue
中引入,并映射成组件标签
MyProfile.vue
<template>
<div>
<default-slot></default-slot>
</div>
</template>
<script>
import DefaultSlot from '@/components/DefaultSlot'
export default {
components: {
DefaultSlot
}
};
</script>
- 需要注意的是这一次的含有插槽的组件中我们什么都没有写,看一看他会渲染成什么样子
- 我们会发现他将插槽中的内容渲染了出来
- 我们在修改一下代码,在组件标签之间传值
<template>
<div>
<default-slot>yes, i love you , too</default-slot>
</div>
</template>
- 我们观察一下,他会被渲染成什么样子?
- 插槽间的内容不见了,变成了我们传入的值,这就是具有默认值的插槽
3. 具名插槽
3.1 基本用法
语法
<template v-slot:xxx>
<slot name="xxx">
什么是具名插槽呢?- 简单的来说就是
<slot>
标签上有name
属性 - 当一个组件内有多个
<slot>
存在的时候,可以通过name
属性进行分别插入
实现需求
- 比如说一个网页中一般有三个部分,头部、内容区、和底部,我们能不能将可变的部分抽出来,固定的部分封装成一个模板呢,就比如说可变的部分放在
<header><main><footer>
标签中呢?
- 在
components
新建NameSlots.vue
,写上如下代码
<template>
<div>
<h3>我是头部,我下面的内容是通过具名插槽传递过来的</h3>
<header>
<slot name="header"></slot>
</header>
<h3>我是内容,我故意没有name属性</h3>
<main>
<slot></slot>
</main>
<h3>我是底部,我下面的内容是通过具名插槽传递过来的</h3>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
-
值得注意的是文件中有三个
<slot>
标签,其中两个有name
属性,一个没有 -
接着我们在
MyProfile.vue
中引入,并映射成组件标签 -
MyProfile.vue
<template>
<h2>具名插槽</h2>
<name-slots>
<template v-slot:header>头部内容,通过 v-slot:header 拉过来的</template>
<template v-slot:footer>底部内容,通过 v-slot:footer 拉过来的</template>
<div>主题内容啊,他们不要的都跑我这里来了,我是垃圾桶</div>
</name-slots>
</div>
</template>
<script>
import NameSlots from "@/components/NameSlots";
export default {
components: {
NameSlots
}
};
</script>
- 我们看看他会被渲染成什么样子?
- 我们发现
<template v-slot:xxx>
就像一个钩子,他会将标签中的内容,勾到相应的位置<slot name="xxx">
,而那些没有name
属性的slot
只能吃残羹剩饭
注意
注意 v-slot 只能添加在
<template>
上
不过你还会遇到以下用法
slot
是一个属性
<template slot='header'>头部内容,通过 v-slot:header 拉过来的</template>
- 或者在标签上直接使用slot
<h3 slot='header'>头部内容,通过 v-slot:header 拉过来的</h3 >
这属于老版本的用法,作用都一样
3.2 缩写
#
只能在template
上使用
<template v-slot:header>头部内容,通过 v-slot:header 拉过来的</template>
//可以缩写为
<template #header>头部内容,通过 v-slot:header 拉过来的</template>
4. 作用域插槽
什么是作用域插槽?
- 作用域插槽能够使我们访问,子组件中的数据,,恰好弥补了我们在插槽基本使用时的缺陷
4.1 作用域插槽的基本使用
- 我们在
components
新建ScopeSlot.vue
,写上如下代码
<template>
<div>
<!-- ta叫做插槽prop -->
<slot v-bind:msg="msg"></slot>
</div>
</template>
<script>
export default {
data () {
return {
msg:'我与<slot>标签在一个组件中,经过我允许(在slot上绑定数据),你才能看到我',
}
},
}
</script>
- 接着我们在
MyProfile.vue
中引入,并映射成组件标签
<template>
<div>
<h2>作用域插槽</h2>
<scope-slot>
<template v-slot:default="slotProps">
<div>{{slotProps.msg}}</div>
</template>
</scope-slot>
</div>
</template>
<script>
import ScopeSlot from '@/components/ScopeSlot'
export default {
components: {
ScopeSlot
}
};
</script>
结果
- 我们发现他已经可以访问到子组件中的数据了
说明
- 绑定在
<slot>
元素上的 attribute 被称为插槽 prop slotProps
就相当于拿到了子组件的data
4.2 独占默认插槽的缩写语法
什么是独占默认插槽?
- 独占:表示一个组件中只有一个插槽
- 默认:没有
name
属性,只是一个<slot>
标签
语法
- 这个时候我们可以把
v-slot
放在组件标签上,并采用缩写方式
使用
2. 我们在components
新建SingleDefault.vue
,写上如下代码
<template>
<div>
<h3>独占默认插槽</h3>
<slot :user='user'></slot>
</div>
</template>
<script>
export default {
data(){
return {
user:{name:"sunwukong",age:18}
}
}
}
</script>
- 接着我们在
MyProfile.vue
中引入,并映射成组件标签
<template>
<div>
<single-default v-slot:default="slotProps">{{slotProps.user.name}}</single-default>
</div>
</template>
<script>
import SingleDefault from "@/components/SingleDefault";
export default {
components: {
SingleDefault
}
};
</script>
- 让我们观察浏览器发生了什么变化?
- 我们访问到了属性
他还可以改变成如下缩写
<single-default v-slot="slotProps">{{slotProps.user.age}}</single-default>
4.3 解构插槽
什么是解构插槽?
- 作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:
function (slotProps) {
// 插槽内容
}
v-slot='对象参数'
,因此我们可以对对象进行解构
语法
v-slot="{user:name}"
,类似于这种形式
我们在上一个例题中接着写,把相应的部分改成
<single-default v-slot='{user:name}'>{{name.name}}</single-default>
- 这里我们使用了解构赋值后的重命名
- 我们会发现他也是行得通的