组件化是Vue中很是核心的概念,若是想要组件化,那必需要对组件进行封装。html
而想要封装组件,那你必定要了解slot才能更好进行封装。vue
什么是插槽?请让我用一张图解释一下数组
概述一下,就是在对已经封装完的组件中插入本身想要定义的不一样组件。markdown
说白了,就是封装的组件中插入子组件,而子组件能够根据本身需求去定义。ide
而slot插槽有三种不一样类型的插槽,分别为匿名插槽、具名插槽、做用域插槽。函数
下面一段代码,教你快速使用匿名插槽oop
<!--组件调用页面-->
<template>
<div class="parent">
<child>
<template>
<p>插入匿名插槽</p>
</template>
</child>
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
components: {
Child
}
}
</script>
复制代码
<!--封装的组件-->
<template>
<div class="child">
<h3>子组件:匿名插槽</h3>
<slot></slot>
</div>
</template>
<style scoped>
.child {
background: #fbd4fc;
}
</style>
复制代码
从代码上看组件化
其实就是在封装组件中,加 slot 标签post
在要使用的标签上,使用 template 标签,再插入本身想要的组件。ui
固然,匿名插槽也能够叫默认插槽,这都是别名,不一样的叫法。
先来看看具名插槽是怎么使用
<!--组件调用页面-->
<template>
<div class="parent">
<child>
<template v-slot:child>
<p>插入具名插槽</p>
</template>
</child>
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
components: {
Child
}
}
</script>
复制代码
<!--封装的组件-->
<template>
<div class="child">
<h3>子组件:具名插槽</h3>
<slot name="child"></slot>
</div>
</template>
<style scoped>
.child {
background: #b2fffc;
}
</style>
复制代码
经过代码能够很容看出
其实就是slot组件上多一个name属性
以及template模板上多了一个v-slot
这样就能够快速“对号入座”
⚠️不过要注意:本文代码基于 vue2.6.0+ 版本
看到这里,或许有小伙伴,有个困惑,具名插槽和默认插槽什么异同呢?
官方文档给出的解释: 下面我提供两个示例,你们一看就能懂
<!--组件调用页面-->
<template>
<div class="parent">
<child>
<template>
<p>若是不使用v-slot:就默认插入匿名插槽</p>
</template>
</child>
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
components: {
Child
}
}
</script>
复制代码
<!--封装的组件-->
<template>
<div class="child">
<header>
<h3>头部div</h3>
<slot name="header"></slot>
</header>
<div class="content">
<h3>中间div</h3>
<!-- 等价于<slot></slot> -->
<slot name="default"></slot>
</div>
<footer>
<h3>尾部div</h3>
<slot name="footer"></slot>
</footer>
</div>
</template>
<style scoped>
header {
background: #a0c0ff;
}
.content {
background: #f8f59a;
}
footer {
background: #ffdfdf;
}
</style>
复制代码
固然了,v-slot指令能够用#代替
<!--组件调用页面-->
<template>
<div class="parent">
<child>
<template #header>
<p>插入header</p>
</template>
<template>
<p>插入中间div</p>
</template>
<template #footer>
<p>插入footer</p>
</template>
</child>
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
components: {
Child
}
}
</script>
复制代码
<!--封装的组件-->
<template>
<div class="child">
<header>
<h3>头部div</h3>
<slot name="header"></slot>
</header>
<div class="content">
<h3>中间div</h3>
<!-- 等价于<slot></slot> -->
<slot name="default"></slot>
</div>
<footer>
<h3>尾部div</h3>
<slot name="footer"></slot>
</footer>
</div>
</template>
<style scoped>
header {
background: #a0c0ff;
}
.content {
background: #f8f59a;
}
footer {
background: #ffdfdf;
}
</style>
复制代码
知道了匿名插槽和具名插槽是远远不够!
由于这两种插槽仅仅只能能把Dom插入到封装好的组件中,
而不能获取组件中的数据,这样有时候是知足不了咱们的需求的。
若是想获取组件的数据,那么仍是得靠做用域插槽!
先来一个例子说明下
<!--组件调用页面-->
<template>
<div class="parent">
<child>
<template slot-scope="childData">
<div v-for="(item, index) in childData.data" :key="index">
<input type="text" :value="item"/>
</div>
</template>
</child>
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
components: {
Child
}
}
</script>
复制代码
<!--封装的组件-->
<template>
<div class="child">
<h3>child组件标题</h3>
<slot :data="list"></slot>
</div>
</template>
<script>
export default {
data () {
return {
list: ['1', '2', '3', '4', '5', '6', '7', '8', '9']
}
}
}
</script>
<style scoped>
</style>
复制代码
看完这段代码,或许有些小伙伴就晕了。
别急,让我稍加说明!
其实简单的理解就是:封装的组件给要插入的组件传值
也能够说是变相的父给子组件传值
而template标签中自定义了 childData
childData 下的 data 也就是 组件内部的 list 数据
由于里面有段代码是 :data = "list"
这样一想简单易懂~
还有细心的小伙伴获取会注意到,我用了一个v-model!
试试例子,就会发现修改Input内容里面数据也会改变
那由于是input标签,vue中有封装本身的v-model
他能够双向绑定,那若是不是input标签,就可能须要自定义组件啦~
固然会有个办法提供给你们
<!--组件调用页面-->
<template>
<div class="parent">
<child>
<template slot-scope="childData">
<div v-for="(item, index) in childData.data.list" :key="index">
<input
type="text"
:value="item"
@input="changeValue(childData.data.change, index, $event)"
/>
</div>
</template>
</child>
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
components: {
Child
},
methods: {
/**
* 改变 input 的 value 方法
* @param change 子组件传入的函数方法(回调函数)
* @param index 索引值
* @param event 获取事件元素
*/
changeValue (change, index, event) {
console.log(111)
const value = event.currentTarget.value
change(index, value)
}
}
}
</script>
复制代码
<template>
<div class="child">
<h3>child组件标题</h3>
<slot :data="{list, change: onChange}"></slot>
</div>
</template>
<script>
export default {
data () {
return {
list: ['1', '2', '3', '4', '5', '6', '7', '8', '9']
}
},
methods: {
/**
* 改变子组件 list 函数方法
* @param index 数组索引值
* @param value 新的 value 值
*/
onChange (index, value) {
this.list[index] = value
}
}
}
</script>
<style scoped>
</style>
复制代码
简单的来讲,就是在组件内部提供一个函数方法去让外部调用修改
若是你对这段话不太了解,那不妨看看另外一篇简短而又干货满满的如何“修改”Vue中的prop~
感谢阅读