深入了解Vue組件七種通信方式
vue組件通信的方式,這是在面試中一個(gè)非常高頻的問題,我剛開始找實(shí)習(xí)便經(jīng)常遇到這個(gè)問題,當(dāng)時(shí)只知道回到props和 $emit,后來隨著學(xué)習(xí)的深入,才發(fā)現(xiàn)vue組件的通信方式竟然有這么多!
今天對(duì)vue組件通信方式進(jìn)行一下總結(jié),如寫的有疏漏之處還請(qǐng)大家留言。
1. props/$emit
簡介
props和 $emit相信大家十分的熟悉了,這是我們最常用的vue通信方式。
props:props可以是數(shù)組或?qū)ο?,用于接收來自父組件通過v-bind傳遞的數(shù)據(jù)。當(dāng)props為數(shù)組時(shí),直接接收父組件傳遞的屬性;當(dāng) props 為對(duì)象時(shí),可以通過type、default、required、validator等配置來設(shè)置屬性的類型、默認(rèn)值、是否必傳和校驗(yàn)規(guī)則。
$emit:在父子組件通信時(shí),我們通常會(huì)使用 $emit來觸發(fā)父組件v-on在子組件上綁定相應(yīng)事件的監(jiān)聽。
代碼實(shí)例
下面通過代碼來實(shí)現(xiàn)一下props和 $emit的父子組件通信,在這個(gè)實(shí)例中,我們都實(shí)現(xiàn)了以下的通信:
父向子傳值:父組件通過 :messageFromParent="message" 將父組件 message 值傳遞給子組件,當(dāng)父組件的 input 標(biāo)簽輸入時(shí),子組件p標(biāo)簽中的內(nèi)容就會(huì)相應(yīng)改變。
子向父傳值:父組件通過 @on-receive="receive" 在子組件上綁定了 receive 事件的監(jiān)聽,子組件 input 標(biāo)簽輸入時(shí),會(huì)觸發(fā) receive 回調(diào)函數(shù), 通過 this.$emit('on-receive', this.message) 將子組件 message 的值賦值給父組件 messageFromChild ,改變父組件p標(biāo)簽的內(nèi)容。
請(qǐng)看代碼:
// 子組件代碼 <template> <div class="child"> <h4>this is child component</h4> <input type="text" v-model="message" @keyup="send" /> <p>收到來自父組件的消息:{{ messageFromParent }}</p> </div> </template> <script> export default { name: 'Child', props: ['messageFromParent'], // 通過props接收父組件傳過來的消息 data() { return { message: '', } }, methods: { send() { this.$emit('on-receive', this.message) // 通過 $emit觸發(fā)on-receive事件,調(diào)用父組件中receive回調(diào),并將this.message作為參數(shù) }, }, } </script>
// 父組件代碼 <template> <div class="parent"> <h3>this is parent component</h3> <input type="text" v-model="message" /> <p>收到來自子組件的消息:{{ messageFromChild }}</p> <Child :messageFromParent="message" @on-receive="receive" /> </div> </template> <script> import Child from './child' export default { name: 'Parent', data() { return { message: '', // 傳遞給子組件的消息 messageFromChild: '', } }, components: { Child, }, methods: { receive(msg) { // 接受子組件的信息,并將其賦值給messageFromChild this.messageFromChild = msg }, }, } </script>
效果預(yù)覽
2. v-slot
簡介
v-slot是 Vue2.6 版本中新增的用于統(tǒng)一實(shí)現(xiàn)插槽和具名插槽的api,用于替代 slot(2.6.0廢棄) 、 slot-scope(2.6.0廢棄) 、 scope(2.5.0廢棄) 等api。
v-slot在 template 標(biāo)簽中用于提供具名插槽或需要接收 prop 的插槽,如果不指定 v-slot ,則取默認(rèn)值 default 。
代碼實(shí)例
下面請(qǐng)看v-slot的代碼實(shí)例,在這個(gè)實(shí)例中我們實(shí)現(xiàn)了:
父向子傳值:父組件通過 <template v-slot:child>{{ message }}</template> 將父組件的message值傳遞給子組件,子組件通過 <slot name="child"></slot> 接收到相應(yīng)內(nèi)容,實(shí)現(xiàn)了父向子傳值。
// 子組件代碼 <template> <div class="child"> <h4>this is child component</h4> <p>收到來自父組件的消息: <slot name="child"></slot> <!--展示父組件通過插槽傳遞的{{message}}--> </p> </div> </template>
<template> <div class="parent"> <h3>this is parent component</h3> <input type="text" v-model="message" /> <Child> <template v-slot:child> {{ message }} <!--插槽要展示的內(nèi)容--> </template> </Child> </div> </template> <script> import Child from './child' export default { name: 'Parent', data() { return { message: '', } }, components: { Child, }, } </script>
效果預(yù)覽
3. $refs/? $parent/ $children/$root
簡介
我們也同樣可以通過 $refs/$parent/$children/$root 等方式獲取 Vue 組件實(shí)例,得到實(shí)例上綁定的屬性及方法等,來實(shí)現(xiàn)組件之間的通信。
$refs:我們通常會(huì)將 $refs綁定在DOM元素上,來獲取DOM元素的 attributes。在實(shí)現(xiàn)組件通信上,我們也可以將 $refs 綁定在子組件上,從而獲取子組件實(shí)例。
$parent:我們可以在 Vue 中直接通過 this.$parent 來獲取當(dāng)前組件的父組件實(shí)例(如果有的話)。
$children:同理,我們也可以在 Vue 中直接通過 this.$children 來獲取當(dāng)前組件的子組件實(shí)例的數(shù)組。但是需要注意的是, this.$children 數(shù)組中的元素下標(biāo)并不一定對(duì)用父組件引用的子組件的順序,例如有異步加載的子組件,可能影響其在 children 數(shù)組中的順序。所以使用時(shí)需要根據(jù)一定的條件例如子組件的name去找到相應(yīng)的子組件。
$root:獲取當(dāng)前組件樹的根 Vue 實(shí)例。如果當(dāng)前實(shí)例沒有父實(shí)例,此實(shí)例將會(huì)是其自己。通過 $root ,我們可以實(shí)現(xiàn)組件之間的跨級(jí)通信。
代碼實(shí)例
下面來看一個(gè) $ parent 和 $ children 使用的實(shí)例(由于這幾個(gè)api的使用方式大同小異,所以關(guān)于 $ refs 和? $ root 的使用就不在這里展開了,在這個(gè)實(shí)例中實(shí)現(xiàn)了:
父向子傳值:子組件通過 $parent.message 獲取到父組件中message的值。
子向父傳值:父組件通過 $children 獲取子組件實(shí)例的數(shù)組,在通過對(duì)數(shù)組進(jìn)行遍歷,通過實(shí)例的 name 獲取到對(duì)應(yīng) Child1 子組件實(shí)例將其賦值給 child1,然后通過 child1.message 獲取到 Child1 子組件的message。
代碼如下:
// 子組件 <template> <div class="child"> <h4>this is child component</h4> <input type="text" v-model="message" /> <p>收到來自父組件的消息:{{ $parent.message }}</p> <!--展示父組件實(shí)例的message--> </div> </template> <script> export default { name: 'Child1', data() { return { message: '', // 父組件通過this.$children可以獲取子組件實(shí)例的message } }, } </script>
// 父組件 <template> <div class="parent"> <h3>this is parent component</h3> <input type="text" v-model="message" /> <p>收到來自子組件的消息:{{ child1.message }}</p> <!--展示子組件實(shí)例的message--> <Child /> </div> </template> <script> import Child from './child' export default { name: 'Parent', data() { return { message: '', child1: {}, } }, components: { Child, }, mounted() { this.child1 = this.$children.find((child) => { return child.$options.name === 'Child1' // 通過options.name獲取對(duì)應(yīng)name的child實(shí)例 }) }, } </script>
效果預(yù)覽
4. $attrs/$listener
簡介
$ attrs和 $ listeners 都是 Vue2.4 中新增加的屬性,主要是用來供使用者用來開發(fā)高級(jí)組件的。
$attrs:用來接收父作用域中不作為 prop 被識(shí)別的 attribute 屬性,并且可以通過 v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建高級(jí)別的組件時(shí)非常有用。
試想一下,當(dāng)你創(chuàng)建了一個(gè)組件,你要接收 param1 、param2、param3 …… 等數(shù)十個(gè)參數(shù),如果通過 props,那你需要通過 props: ['param1', 'param2', 'param3', ……] 等聲明一大堆。如果這些 props 還有一些需要往更深層次的子組件傳遞,那將會(huì)更加麻煩。
而使用 $attrs ,你不需要任何聲明,直接通過 $attrs.param1 、 $attrs.param2 ……就可以使用,而且向深層子組件傳遞上面也給了示例,十分方便。
$listeners:包含了父作用域中的 v-on 事件監(jiān)聽器。它可以通過 v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時(shí)非常有用,這里在傳遞時(shí)的使用方法和 $attrs 十分類似。
代碼實(shí)例
在這個(gè)實(shí)例中,共有三個(gè)組件:A、B、C,其關(guān)系為:[ A [ B [C] ] ],A為B的父組件,B為C的父組件。即:1級(jí)組件A,2級(jí)組件B,3級(jí)組件C。我們實(shí)現(xiàn)了:
父向子傳值:1級(jí)組件A通過 :messageFromA="message" 將 message 屬性傳遞給2級(jí)組件B,2級(jí)組件B通過 $attrs.messageFromA 獲取到1級(jí)組件A的 message 。
:messageFromA="message" v-bind="$attrs" $attrs.messageFromA
子向父傳值:1級(jí)組件A通過 @keyup="receive" 在子孫組件上綁定keyup事件的監(jiān)聽,2級(jí)組件B在通過 v-on="$listeners" 來將 keyup 事件綁定在其 input 標(biāo)簽上。當(dāng)2級(jí)組件B input 輸入框輸入時(shí),便會(huì)觸發(fā)1級(jí)組件A的receive回調(diào),將2級(jí)組件B的 input 輸入框中的值賦值給1級(jí)組件A的 messageFromComp ,從而實(shí)現(xiàn)子向父傳值。
@keyup="receive" <CompC v-on="$listeners" /> v-on="$listeners"
代碼如下:
// 3級(jí)組件C <template> <div class="compc"> <h5>this is C component</h5> <input name="compC" type="text" v-model="message" v-on="$listeners" /> <!--將A組件keyup的監(jiān)聽回調(diào)綁在該input上--> <p>收到來自A組件的消息:{{ $attrs.messageFromA }}</p> </div> </template> <script> export default { name: 'Compc', data() { return { message: '', } }, } </script>
// 2級(jí)組件B <template> <div class="compb"> <h4>this is B component</h4> <input name="compB" type="text" v-model="message" v-on="$listeners" /> <!--將A組件keyup的監(jiān)聽回調(diào)綁在該input上--> <p>收到來自A組件的消息:{{ $attrs.messageFromA }}</p> <CompC v-bind="$attrs" v-on="$listeners" /> <!--將A組件keyup的監(jiān)聽回調(diào)繼續(xù)傳遞給C組件,將A組件傳遞的attrs繼續(xù)傳遞給C組件--> </div> </template> <script> import CompC from './compC' export default { name: 'CompB', components: { CompC, }, data() { return { message: '', } }, } </script>
// A組件 <template> <div class="compa"> <h3>this is A component</h3> <input type="text" v-model="message" /> <p>收到來自{{ comp }}的消息:{{ messageFromComp }}</p> <CompB :messageFromA="message" @keyup="receive" /> <!--監(jiān)聽子孫組件的keyup事件,將message傳遞給子孫組件--> </div> </template> <script> import CompB from './compB' export default { name: 'CompA', data() { return { message: '', messageFromComp: '', comp: '', } }, components: { CompB, }, methods: { receive(e) { // 監(jiān)聽子孫組件keyup事件的回調(diào),并將keyup所在input輸入框的值賦值給messageFromComp this.comp = e.target.name this.messageFromComp = e.target.value }, }, } </script>
效果預(yù)覽
5. provide/inject
簡介
provide/inject這對(duì)選項(xiàng)需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴,不論組件層次有多深,并在其上下游關(guān)系成立的時(shí)間里始終生效。如果你是熟悉React的同學(xué),你一定會(huì)立刻想到Context這個(gè)api,二者是十分相似的。
provide:是一個(gè)對(duì)象,或者是一個(gè)返回對(duì)象的函數(shù)。該對(duì)象包含可注入其子孫的 property ,即要傳遞給子孫的屬性和屬性值。
injcet:一個(gè)字符串?dāng)?shù)組,或者是一個(gè)對(duì)象。當(dāng)其為字符串?dāng)?shù)組時(shí),使用方式和props十分相似,只不過接收的屬性由data變成了provide中的屬性。當(dāng)其為對(duì)象時(shí),也和props類似,可以通過配置default和from等屬性來設(shè)置默認(rèn)值,在子組件中使用新的命名屬性等。
代碼實(shí)例
這個(gè)實(shí)例中有三個(gè)組件,1級(jí)組件A,2級(jí)組件B,3級(jí)組件C:[ A [ B [C] ] ],A是B的父組件,B是C的父組件。實(shí)例中實(shí)現(xiàn)了:
父向子傳值:1級(jí)組件A通過provide將message注入給子孫組件,2級(jí)組件B通過 inject: ['messageFromA'] 來接收1級(jí)組件A中的message,并通過 messageFromA.content 獲取1級(jí)組件A中message的content屬性值。
跨級(jí)向下傳值:1級(jí)組件A通過provide將message注入給子孫組件,3級(jí)組件C通過 inject: ['messageFromA'] 來接收1級(jí)組件A中的message,并通過 messageFromA.content 獲取1級(jí)組件A中message的content屬性值,實(shí)現(xiàn)跨級(jí)向下傳值。
代碼如下:
// 1級(jí)組件A <template> <div class="compa"> <h3>this is A component</h3> <input type="text" v-model="message.content" /> <CompB /> </div> </template> <script> import CompB from './compB' export default { name: 'CompA', provide() { return { messageFromA: this.message, // 將message通過provide傳遞給子孫組件 } }, data() { return { message: { content: '', }, } }, components: { CompB, }, } </script>
// 2級(jí)組件B <template> <div class="compb"> <h4>this is B component</h4> <p>收到來自A組件的消息:{{ messageFromA && messageFromA.content }}</p> <CompC /> </div> </template> <script> import CompC from './compC' export default { name: 'CompB', inject: ['messageFromA'], // 通過inject接受A中provide傳遞過來的message components: { CompC, }, } </script>
// 3級(jí)組件C <template> <div class="compc"> <h5>this is C component</h5> <p>收到來自A組件的消息:{{ messageFromA && messageFromA.content }}</p> </div> </template> <script> export default { name: 'Compc', inject: ['messageFromA'], // 通過inject接受A中provide傳遞過來的message } </script>
注意點(diǎn):
可能有同學(xué)想問我上面1級(jí)組件A中的message為什么要用object類型而不是string類型,因?yàn)樵趘ue provide 和 inject 綁定并不是可響應(yīng)的。如果message是string類型,在1級(jí)組件A中通過input輸入框改變message值后無法再賦值給messageFromA,如果是object類型,當(dāng)對(duì)象屬性值改變后,messageFromA里面的屬性值還是可以隨之改變的,子孫組件inject接收到的對(duì)象屬性值也可以相應(yīng)變化。
子孫provide和祖先同樣的屬性,會(huì)在后代中覆蓋祖先的provide值。例如2級(jí)組件B中也通過provide向3級(jí)組件C中注入一個(gè)messageFromA的值,則3級(jí)組件C中的messageFromA會(huì)優(yōu)先接收2級(jí)組件B注入的值而不是1級(jí)組件A。
效果預(yù)覽
6. eventBus
簡介
eventBus又稱事件總線,通過注冊(cè)一個(gè)新的Vue實(shí)例,通過調(diào)用這個(gè)實(shí)例的 $ emit 和 $ on等來監(jiān)聽和觸發(fā)這個(gè)實(shí)例的事件,通過傳入?yún)?shù)從而實(shí)現(xiàn)組件的全局通信。它是一個(gè)不具備 DOM 的組件,有的僅僅只是它實(shí)例方法而已,因此非常的輕便。
我們可以通過在全局Vue實(shí)例上注冊(cè):
// main.js Vue.prototype.$Bus = new Vue()
但是當(dāng)項(xiàng)目過大時(shí),我們最好將事件總線抽象為單個(gè)文件,將其導(dǎo)入到需要使用的每個(gè)組件文件中。這樣,它不會(huì)污染全局命名空間:
// bus.js,使用時(shí)通過import引入 import Vue from 'vue' export const Bus = new Vue()
原理分析
eventBus的原理其實(shí)比較簡單,就是使用訂閱-發(fā)布模式,實(shí)現(xiàn) $ emit 和 $ on兩個(gè)方法即可:
// eventBus原理 export default class Bus { constructor() { this.callbacks = {} } $on(event, fn) { this.callbacks[event] = this.callbacks[event] || [] this.callbacks[event].push(fn) } $emit(event, args) { this.callbacks[event].forEach((fn) => { fn(args) }) } } // 在main.js中引入以下 // Vue.prototype.$bus = new Bus()
代碼實(shí)例
在這個(gè)實(shí)例中,共包含了4個(gè)組件:[ A [ B [ C、D ] ] ],1級(jí)組件A,2級(jí)組件B,3級(jí)組件C和3級(jí)組件D。我們通過使用eventBus實(shí)現(xiàn)了:
全局通信:即包括了父子組件相互通信、兄弟組件相互通信、跨級(jí)組件相互通信。4個(gè)組件的操作邏輯相同,都是在input輸入框時(shí),通過 this.$bus.$emit('sendMessage', obj) 觸發(fā)sendMessage事件回調(diào),將sender和message封裝成對(duì)象作為參數(shù)傳入;同時(shí)通過 this.$bus.$on('sendMessage', obj) 監(jiān)聽其他組件的sendMessage事件,實(shí)例當(dāng)前組件示例sender和message的值。這樣任一組件input輸入框值改變時(shí),其他組件都能接收到相應(yīng)的信息,實(shí)現(xiàn)全局通信。
代碼如下:
// main.js Vue.prototype.$bus = new Vue()
// 1級(jí)組件A <template> <div class="containerA"> <h2>this is CompA</h2> <input type="text" v-model="message" @keyup="sendMessage" /> <p v-show="messageFromBus && sender !== $options.name"> 收到{{ sender }}的消息:{{ messageFromBus }} </p> <CompB /> </div> </template> <script> import CompB from './compB' export default { name: 'CompA', components: { CompB, }, data() { return { message: '', messageFromBus: '', sender: '', } }, mounted() { this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件 const { sender, message } = obj this.sender = sender this.messageFromBus = message }) }, methods: { sendMessage() { this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件 sender: this.$options.name, message: this.message, }) }, }, } </script>
// 2級(jí)組件B <template> <div class="containerB"> <h3>this is CompB</h3> <input type="text" v-model="message" @keyup="sendMessage" /> <p v-show="messageFromBus && sender !== $options.name"> 收到{{ sender }}的消息:{{ messageFromBus }} </p> <CompC /> <CompD /> </div> </template> <script> import CompC from './compC' import CompD from './compD' export default { name: 'CompB', components: { CompC, CompD, }, data() { return { message: '', messageFromBus: '', sender: '', } }, mounted() { this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件 const { sender, message } = obj this.sender = sender this.messageFromBus = message }) }, methods: { sendMessage() { this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件 sender: this.$options.name, message: this.message, }) }, }, } </script>
// 3級(jí)組件C <template> <div class="containerC"> <p>this is CompC</p> <input type="text" v-model="message" @keyup="sendMessage" /> <p v-show="messageFromBus && sender !== $options.name"> 收到{{ sender }}的消息:{{ messageFromBus }} </p> </div> </template> <script> export default { name: 'CompC', data() { return { message: '', messageFromBus: '', sender: '', } }, mounted() { this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件 const { sender, message } = obj this.sender = sender this.messageFromBus = message }) }, methods: { sendMessage() { this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件 sender: this.$options.name, message: this.message, }) }, }, } </script>
// 3級(jí)組件D <template> <div class="containerD"> <p>this is CompD</p> <input type="text" v-model="message" @keyup="sendMessage" /> <p v-show="messageFromBus && sender !== $options.name"> 收到{{ sender }}的消息:{{ messageFromBus }} </p> </div> </template> <script> export default { name: 'CompD', data() { return { message: '', messageFromBus: '', sender: '', } }, mounted() { this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件 const { sender, message } = obj this.sender = sender this.messageFromBus = message }) }, methods: { sendMessage() { this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件 sender: this.$options.name, message: this.message, }) }, }, } </script>
效果預(yù)覽
圖片過大,截圖處理
7. Vuex
當(dāng)項(xiàng)目龐大以后,在多人維護(hù)同一個(gè)項(xiàng)目時(shí),如果使用事件總線進(jìn)行全局通信,容易讓全局的變量的變化難以預(yù)測(cè)。于是有了Vuex的誕生。
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
有關(guān)Vuex的內(nèi)容,可以參考 Vuex官方文檔 [1] ,我就不在這里班門弄斧了,直接看代碼。
代碼實(shí)例
Vuex的實(shí)例和事件總線leisi,同樣是包含了4個(gè)組件:[ A [ B [ C、D ] ] ],1級(jí)組件A,2級(jí)組件B,3級(jí)組件C和3級(jí)組件D。我們?cè)谶@個(gè)實(shí)例中實(shí)現(xiàn)了:
全局通信:代碼的內(nèi)容和eventBus也類似,不過要比eventBus使用方便很多。每個(gè)組件通過watch監(jiān)聽input輸入框的變化,把input的值通過vuex的commit觸發(fā)mutations,從而改變stroe的值。然后每個(gè)組件都通過computed動(dòng)態(tài)獲取store中的數(shù)據(jù),從而實(shí)現(xiàn)全局通信。
// store.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { message: { sender: '', content: '', }, }, mutations: { sendMessage(state, obj) { state.message = { sender: obj.sender, content: obj.content, } }, }, })
// 組件A <template> <div class="containerA"> <h2>this is CompA</h2> <input type="text" v-model="message" /> <p v-show="messageFromStore && sender !== $options.name"> 收到{{ sender }}的消息:{{ messageFromStore }} </p> <CompB /> </div> </template> <script> import CompB from './compB' export default { name: 'CompA', components: { CompB, }, data() { return { message: '', } }, computed: { messageFromStore() { return this.$store.state.message.content }, sender() { return this.$store.state.message.sender }, }, watch: { message(newValue) { this.$store.commit('sendMessage', { sender: this.$options.name, content: newValue, }) }, }, } </script>
同樣和eventBus中一樣,B,C,D組件中的代碼除了引入子組件的不同,script部分都是一樣的,就不再往上寫了。
效果預(yù)覽
總結(jié)
上面總共提到了7中Vue的組件通信方式,他們能夠進(jìn)行的通信種類如下圖所示:
- props/$emit:可以實(shí)現(xiàn)父子組件的雙向通信,在日常的父子組件通信中一般會(huì)作為我們的最常用選擇。
- v-slot:可以實(shí)現(xiàn)父子組件單向通信(父向子傳值),在實(shí)現(xiàn)可復(fù)用組件,向組件中傳入DOM節(jié)點(diǎn)、html等內(nèi)容以及某些組件庫的表格值二次處理等情況時(shí),可以優(yōu)先考慮v-slot。
- $ refs/$ parent/ $ children/ $ r oot: 可 以實(shí)現(xiàn)父子組件雙向通信,其中 $root可以實(shí)現(xiàn)根組件實(shí)例向子孫組件跨級(jí)單向傳值。 在父組件沒有傳遞值或通過v-on綁定監(jiān)聽時(shí),父子間想要獲取彼此的屬性或方法可以考慮使用這些api。
- $ attrs/ $ listeners: 能夠?qū)崿F(xiàn)跨級(jí)雙向通信,能夠讓你簡單的獲取傳入的屬性和綁定的監(jiān)聽,并且方便地向下級(jí)子組件傳遞,在構(gòu)建高級(jí)組件時(shí)十分好用。
- provide/inject:可以實(shí)現(xiàn)跨級(jí)單向通信,輕量地向子孫組件注入依賴,這是你在實(shí)現(xiàn)高級(jí)組件、創(chuàng)建組件庫時(shí)的不二之選。
- eventBus:可以實(shí)現(xiàn)全局通信,在項(xiàng)目規(guī)模不大的情況下,可以利用eventBus實(shí)現(xiàn)全局的事件監(jiān)聽。但是eventBus要慎用,避免全局污染和內(nèi)存泄漏等情況。
- Vuex:可以實(shí)現(xiàn)全局通信,是vue項(xiàng)目全局狀態(tài)管理的最佳實(shí)踐。在項(xiàng)目比較龐大,想要集中式管理全局組件狀態(tài)時(shí),那么安裝Vuex準(zhǔn)沒錯(cuò)!
?以上就是深入了解Vue組件七種通信方式的詳細(xì)內(nèi)容,更多關(guān)于Vue組件通信方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何在Vue中使localStorage具有響應(yīng)式(思想實(shí)驗(yàn))
這篇文章主要介紹了如何在Vue中使localStorage具有響應(yīng)式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07vue echarts實(shí)現(xiàn)柱狀圖動(dòng)態(tài)展示
這篇文章主要為大家詳細(xì)介紹了vue echarts實(shí)現(xiàn)柱狀圖動(dòng)態(tài)展示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09在Vue項(xiàng)目中引入騰訊驗(yàn)證碼服務(wù)的教程
這篇文章主要介紹了在Vue項(xiàng)目中引入騰訊驗(yàn)證碼服務(wù)的教程,需要的朋友可以參考下2018-04-04vue如何通過點(diǎn)擊事件實(shí)現(xiàn)頁面跳轉(zhuǎn)詳解
頁面跳轉(zhuǎn),我們一般都通過路由跳轉(zhuǎn)實(shí)現(xiàn),通常情況下可直接使用router-link標(biāo)簽實(shí)現(xiàn)頁面跳轉(zhuǎn),下面這篇文章主要給大家介紹了關(guān)于vue如何通過點(diǎn)擊事件實(shí)現(xiàn)頁面跳轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下2022-07-07vue左右側(cè)聯(lián)動(dòng)滾動(dòng)的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue左右側(cè)聯(lián)動(dòng)滾動(dòng)的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06Vue網(wǎng)頁html轉(zhuǎn)換PDF(最低兼容ie10)的思路詳解
這篇文章主要介紹了Vue網(wǎng)頁html轉(zhuǎn)換PDF(最低兼容ie10)的思路詳解,實(shí)現(xiàn)此功能需要引入兩個(gè)插件,需要的朋友可以參考下2017-08-08