前言
一篇小總結(jié)姨丈,組件間的通信問題,把v-model擅腰、作用域插槽也歸入了构挤。
通信場景
- 父傳子
- 子傳父
- 父子同步
- 非父子
父傳子
父傳子也可以分為兩種情況
- 傳數(shù)據(jù):props
- 傳html:slot
傳數(shù)據(jù)
這個(gè)是最基本的一般就是父組件用v-bind動(dòng)態(tài)賦值,props在子組件內(nèi)相當(dāng)于在子組件內(nèi)新建了一個(gè)data惕鼓,props可以為字符串?dāng)?shù)組,也可以是對象唐础,為對象時(shí)則可以設(shè)置類型檢查和默認(rèn)值箱歧,如果想在子組件更改傳進(jìn)來的數(shù)據(jù)可以通過data引用或計(jì)算屬性來轉(zhuǎn)換。
傳html
也就是插槽一膨,基礎(chǔ)的html標(biāo)簽中是可以寫html或字符的呀邢,而在如果自定義組件標(biāo)簽內(nèi)寫,就會(huì)--什么都不會(huì)發(fā)生豹绪。因?yàn)樵谧咏M件內(nèi)沒有定義插槽价淌,如果在子組件內(nèi)有slot,則傳入的內(nèi)容就會(huì)顯示在插槽處瞒津。傳的多的話就要有name來區(qū)分
例子
-----子組件---------
<template>
<div class="child">
<p>這是子組件</p>
<slot name='first'>我是默認(rèn)內(nèi)容</slot>
<slot name='second'>我是默認(rèn)內(nèi)容</slot>
<slot name='third'>我是默認(rèn)內(nèi)容</slot>
</div>
</template>
---------父組件-----------
<template>
<div class="parent">
<my-child>
<p slot='first'>我在父組件寫但是在子組件顯示</p>
<template slot="second">
<h1>我是父組件寫的標(biāo)題</h1>
<p>我是父組件寫的文章</p>
</template>
<h1 slot='third'>標(biāo)題是{{title}}</h1>
</my-child>
<p>這是父組件</p>
</div>
</template>
渲染結(jié)果
總之就是花樣傳進(jìn)去html蝉衣,更復(fù)雜的作用域插槽在子傳父寫
子傳父
這個(gè)都是傳數(shù)據(jù)臂港,方法有以下幾種
- 通過事件向父組件發(fā)送消息
- 作用域插槽
事件傳信
在父組件的子組件標(biāo)簽上監(jiān)聽事件侥锦,就像監(jiān)聽一個(gè)click一樣,監(jiān)聽一個(gè)自定義事件中狂,而這個(gè)事件的觸發(fā)卻在子組件內(nèi)屁柏,例子啦膜,子組件的按鈕會(huì)發(fā)出事件信號(hào)add有送,在父組件中的子組件標(biāo)簽上注冊監(jiān)聽,監(jiān)聽到則觸發(fā)僧家。
----------------子組件--------
<p>這是子組件</p>
<button @click="$emit('add')">子組件</button>
----------------父組件-------------
<my-child v-on:add ='count += 1'></my-child >
<p>{{count}}</p>
<p>這是父組件</p>
根據(jù)上面的例子進(jìn)一步雀摘,
$emit
的第二個(gè)參數(shù)可以通過事件傳值,在父組件中通過訪問$event
接收 例子這樣就是點(diǎn)一下加3了八拱。如果事件是函數(shù)那值會(huì)稱為函數(shù)的第一個(gè)參數(shù)阵赠,無需$event
----------------子組件--------
<p>這是子組件</p>
<button @click="$emit('add',3)">子組件</button>
----------------父組件-------------
<my-child v-on:add ='count += $event'></my-child >
<p>{{count}}</p>
<p>這是父組件</p>
作用域插槽
這個(gè)作用域插槽是勉強(qiáng)可以放到子向父傳數(shù)據(jù),雖然還是要還給子組件乘粒,上面插槽可知豌注,子組件內(nèi)部的slot在父組件未向其傳內(nèi)容時(shí)是不顯示或顯示默認(rèn)內(nèi)容的,但是如果父組件指向向子組件傳遞html和css但是內(nèi)容卻由子組件自己提供呢灯萍?在父組件內(nèi)不管{{}}寫到哪轧铁,它能訪問的都是父組件的作用域,現(xiàn)在我們需要在父組件的子標(biāo)簽內(nèi)訪問子標(biāo)簽的作用域
---------------------子組件-------------------------
<template>
<div class="child">
<p>這是子組件</p>
<slot :data='data'> </slot>
</div>
</template>
<script>
export default {
data() {
return {
data: ['子數(shù)據(jù)1','子數(shù)據(jù)2']
}
},
}
</script>
----------------------父組件----------------------
<template>
<div class="parent">
<my-child >
<template slot-scope='scope'> // scope就是個(gè)名字代表著子組件作用域
{{scope.data}}
</template>
</my-child >
<p>這是父組件</p>
</div>
</template>
子組件內(nèi)slot通過bind綁定data旦棉,在父組件內(nèi)給它取個(gè)名叫scope齿风,slot-scope='scope'就可以訪問了。懶得起名就用解構(gòu)賦值slot-scope={data}
父子同步
也就是prop的雙向綁定绑洛,單向數(shù)據(jù)流不可能雙向綁定的救斑,但是通過父通過props傳子,子通過$emit傳父真屯,父在傳回來可以實(shí)現(xiàn)同步
-----------------子組件-------------------------
<div class="child">
<p>這是子組件</p>
<button @click="$emit('update:title',childTitle)">更新標(biāo)題</button>
<p>{{title}}</p>
</div>
-----------------父組件---------------------
<div class="parent">
<my-child :title="title" v-on:update:title='title = $event'></my-child >
<p>這是父組件</p>
</div>
簡寫
<my-child :title.sync="title"></my-child >
v-model
v-model也是一個(gè)意思脸候,一個(gè)組件上的 v-model 默認(rèn)會(huì)利用名為 value 的 prop 和名為 input 的事件。默認(rèn)傳遞value進(jìn)去又默認(rèn)監(jiān)聽input事件绑蔫,且監(jiān)聽后將傳過來的值賦給value运沦。
<input
type="text"
v-model="something">
<!--等價(jià)于-->
<input
type="text"
v-bind:value="something"
v-on:input="something = $event.target.value">
非父子
也就是同級(jí)組件或?qū)O子組件之類的,一種方法是用一個(gè)空的vue實(shí)例當(dāng)作中央事件總線配深,當(dāng)作中介携添。組件通過on監(jiān)聽事件來接受篓叶,很好理解烈掠。
一種就是使用vuex。雖然官方推薦項(xiàng)目比較大時(shí)才使用缸托,但是vuex語法簡單左敌,可以塞異步方法進(jìn)去,配合調(diào)試工具數(shù)據(jù)流清晰俐镐。不管大小直接就用母谎。