組件化是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~
感謝閱讀