一文带你吃透Vue_slot、具名、作用域插槽
一文带你吃透Vue_插槽,对vue官方的废弃和更新插槽语法进行了总结,快到文里来
一文带你吃透Vue_slot插槽
vue中的插槽
前言
看了很多文章讲插槽,觉得不是很清晰并且年代太久了,这里给大家仔细地讲一讲,并且自vue官方2.6.0以后对具名插槽、作用于插槽的使用做出了更新,在这里这也大家做出了语法总结,我们分别在html中和vue实际项目中对插槽进行讲解
提示:文章有点长,但绝对不会让你感到枯燥,结合实例进行讲解
一、Vue插槽是什么?
插槽是子组件中
的,提供给父组件使用的一个占位
符, 用slot表示, 父组件可以在这个占位符中填充任何模板代码, 如HTML,组件等,填充的内容会替换
子组件的slot标签;
等等等等,看这段话可能对小白有些生硬 |
我们来深入的了解一下
插槽就是父组件要多次渲染同一个子组件的时候,想要(抽取共性,保留不同)
更改或者添加一些数据:
- 添加
- 替换
例如一个导航栏,我们在切换不同页面时,导航栏是略有不同的,比如图标,样式,但他们调用的是相同的组件,我们要如何做到修改呢
我们先以简单的实例对插槽进行讲解
二、插槽的简单示例
1.slot插槽
请看:
- Vue实例是父组件,我们在其中注册一个名为cpn的子组件
- 我们使用了四次cpn这个组件,想要在cpn标签的位置添加或修改一些东西,可并不能达到我们的效果
我们在子组件中添加slot属性
再来看,我们在cpn组件中写的内容替换掉了slot,这里由于写法死板,只有我们上面提到的添加属性(保留了组件原本内容,在slot位置进行添加要替换的内容)
所以你是否可以理解
插槽就是父组件想要多次渲染同一个子组件的时候,想要(抽取共性,保留不同)更改或者添加一些数据
2.具名插槽
有时候我们想要单独的修改众多插槽中的一个元素,这就用到了 具名插槽
还是以上面实例讲解
我们想要 单独的修改其中一个,发现根本不行,这时候我们就要使用具名插槽,给插槽 定义name属性来做到具名的效果
防止与普通插槽混淆,先定义name属性,然后我们在app父组件中使用时仍然采用普通插槽的写法,是不是起不到相应的效果,cpn组件会把内容全部替换
再看这时,我们先来梳理一下这个结构 |
这里我们在子组件定义了三个name属性,在父组件中使用了三次cpn这个子组件所以效果有三行,注意span标签是行内元素
,我们一行一行来看
- 第一个cpn:
我们分别定义了两个left、center属性,我们发现slot属性值和name值如果相同会替换掉slot标签,而name="right"这个属性在app父组件并没有定义,所以就保留了下来
- 第二个cpn:
我们在父组件只定义了slot=“center”,由于没有写值所以就是空替换了cpn里的center,所以不显示,只保留了左边、右边
- 第三个cpn:
亦是如此,你是否发现了规律
相同的属性值会单独的进行替换,不同的则会被保留,具名插槽的作用就是根据名称进行特定的修改
3.作用域插槽
一句话:
作用域插槽:
让插槽内容能够访问子组件中才有的数据
前面的具名插槽可以我们能够按自己想法修改其中的部分插槽,可如果子组件中有数据,我们同样想把数据在父组件上渲染,这时就用到了作用域插槽
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn>
<template v-slot:default="slotPreps">
{{slotPreps.preps}}
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot v-bind:preps="preps">
<ul>
<li v-for="item in preps">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../JS/vue.js"></script>
<script>
const cpn={
template:`#cpn`,
data(){
return{
preps:['蜘蛛侠','美队','钢铁侠','黑寡妇','超人']
}
}
}
const app = new Vue({
el:'#app',
data:{
message:'VUe开始了',
},
components:{
cpn
},
method:{
}
})
</script>
</body>
</html>
讲解
我们可以看到定义在子组件cpn里的数组preps
在父组件里使用一次cpn组件
这时候我们想要换一种渲染格式或者显示部分数据就遇到了难题,数据是子组件的,我们想要在父组件中修改并渲染就必须拿到这个preps数组
作用域插槽对我们很友好
原有的slot和slot-scope都被v-slot代替,可能大家会不适应,但确实简化了一些复杂语法
v-slot:你想定义的名称
="vue给出的作用域的映射
(他会直接映射到你v-bind后面的内容)"
三、slot语法的废弃和更新
vue官方的更新和废弃的插槽语法可以看一下
下面也在讲,如果觉得官方的晦涩难懂就继续往下看就好
更新废弃整理:
废弃的具名插槽: |
在 template标签上使用特殊的 slot 如
<template slot="header">
<h1>Here might be a page title</h1>
</template>
或者直接把 slot attribute 用在一个普通元素上:
<h1 slot="header">Here might be a page title</h1>
更新为 |
<cpn>
<template v-slot:item-icon>
<i class="fa fa-shopping-cart"></i>
</template>
<template v-slot:item-text>
<div >首页</div>
</template>
<cpn>
slot更新为v-slot并且需要tempalte外包
废弃的作用域插槽: |
在 上使用特殊的 slot-scope attribute
<slot-example>
<template slot="default" slot-scope="slotProps">
{{ slotProps.msg }}
</template>
</slot-example>
slot-scope attribute 也可以直接用于非 元素 (含组件)
<slot-example>
<span slot-scope="slotProps">
{{ slotProps.msg }}
</span>
</slot-example>
更新为 |
<cpn>
<template v-slot:default="Preps">
<div>{{Preps.preps}}</div>
<div>{{Preps.preps[1]}}</div>
</template>
</cpn>
slot-scope更新为v-slot并且需要tempalte外包
`
四、Vue项目中插槽的使用
由于Vue官方在2.0.6版本后做出了更新,我们想要在Vue项目中使用具名插槽,我们需要用v-slot并且用template标签包起来
<template v-slot:item-icon>
<i class="fa fa-shopping-cart"></i>
</template>
<template v-slot:item-text>
<div >首页</div>
</template>
所以我们讲讲在Vue项目中如何使用具名插槽进行模板组件抽离,使其变得便于修改和维护,我们以tabbar导航栏为例
效果图
//这里先给上源码,一共三个文件,App.vue TabBar.vue TabBarItem.vue
其实真正的项目App.vue里是很干净的,这里写了这么多是因为层级关系少一点方便大家理解,并且我们主要是讲具名插槽的,如果想,完全可以再把App.vue的东西抽离出去在封装成别的组件
TabBar作为整体
TabBarItem
目录结构
App.vue
<template>
<div id="app">
<tab-bar>
<tab-bar-item>
<template v-slot:item-icon>//图标
<i class="fa fa-shopping-cart"></i>
</template>
<template v-slot:item-text>//文本
<div >首页</div>
</template>
</tab-bar-item>
<tab-bar-item>
<template v-slot:item-icon>
<i class="fa fa-align-justify"></i>
</template>
<template v-slot:item-text>
<div >分类</div>
</template>
</tab-bar-item>
<tab-bar-item>
<template v-slot:item-icon>
<i class="fa fa-shopping-cart"></i>
</template>
<template v-slot:item-text>
<div >购物车</div>
</template>
</tab-bar-item>
<tab-bar-item>
<template v-slot:item-icon>
<i class="fa fa-google-wallet"></i>
</template>
<template v-slot:item-text>
<div>我的</div>
</template>
</tab-bar-item>
</tab-bar>
</div>
<router-view/>
</template>
<script>
import TabBar from './components/TabBar/TabBar'
import TabBarItem from './components/TabBar/TabBarItem';
export default {
name:'App',
components:{
TabBar,
TabBarItem
}
}
</script>
<style>
/*style里面引用的固定格式*/
@import "assets/css/base.css";
</style>
base.css想加可以加上
TabBar
<template>
<div id="tab-bar">
<!-- 父组件中的内容会替换掉slot,就是App.vue中的tab-bar-item相当于在slot的位置-->
<slot></slot>
</div>
</template>
<script>
export default {
name: "TabBar"
}
</script>
<style scoped>
#tab-bar{
display:flex;
background-color: #f6f6f6;
/*固定底部*/
position:fixed;
left:0;
right:0;
bottom:0;
box-shadow: 0px 0px 10px -5px
}
</style>
TabBarItem
<template>
<div class="tab-bar-item">
<slot name="item-icon"></slot>
<slot name="item-text"></slot>
</div>
</template>
<script>
export default {
name: "TabBarItem"
}
</script>
<style scoped>
.tab-bar-item{
/*水平分布,居中*/
flex:1;
text-align:center;
/*移动端的tabbar高度一般都为49px;*/
height:49px;
}
</style>
因为要把组件抽离出来方便修改,所以在这里不带着大家一步步讲解,我们主要是讲Vue项目中的具名插槽的
我们可以看到这里的关系,TabBar和TabBarItem同样都作为App.vue这个父组件的子组件
我们在App.vue中使用了一次tab-bar组件
和四次tab-bar-item组件
,也就是一个整体导航栏和四个item,想要添加和修改是不是变得非常简单
还记得我们的slot插槽吗,这里是普通插槽,定义在子组件中,也就是父组件中的tab-bar组件会替换掉slot
所以你是否明白,这里如果不搞这么多封装,把四个tab-bar-item组件写在slot标签的位置是一个效果
我们来具体的看看item组件,我们定义了两个具名插槽,分别是图标和文本,整体包裹一个class选择器用于修改样式
我们回到App.vue,我们定义v-slot的属性值和item子组件中name值保持一致就会进行替换,来达到每个Item都有不同的图标和名称,进而对子组件进行渲染
你懂了吗?
更多推荐
所有评论(0)