Vue 組件的通訊方式都有哪些?

說一下 Vue 組件的通訊方式都有哪些?(父子組件,兄弟組件,多級嵌套組件等等)

  • 1、父組件向子組件傳值
  • 2、子組件向父組件傳值
  • 3、兄弟組件傳值
  • 4、跨組件

 

1、父組件向子組件傳值

1.1props方式:能夠是數組或對象,用於接收父組件的數據javascript

<div id="app"> <child-component :msg="message" :count="count"></child-component> <button @click="count++"> 點擊+1 </button> </div> <script> const childComponent = { props: { msg: String count: Number }, template: `<div><p>{{msg}}</p><p>{{count}}</p><div>` } new Vue({ el: '#app', data: { message:'父組件的值', count:0 }, components:{ childComponent } }) </script> 

1.2 經過$parent獲取父組件實例的方法或者屬性html

這種方式,從嚴格意義上講不是值的傳遞,而是一種 「取」 (不推薦直接經過實例進行值的獲取)vue

實例屬性$parent能夠得到父組件的實例,藉助實例能夠調用父實例中的方法,或者父實例上的屬性java

<div id="app"> <child-component :msg="message" :count="count"></child-component> <button @click="count++"> 點擊+1 </button> </div> <script> //子組件 const childComponent = { data:() => ({ msg:'', count:null }), methods: { handleClick(){ //調用父級實例的方法 this.$parent.parentMethods(); } } mounted () { // 獲取父級實例中的屬性 this.msg = this.$parent.message; this.count = this.$parent.count; } template: `<div><p @click="handleClick">{{msg}}</p><p>{{count}}</p><div>` } // 父級 new Vue({ el: '#app', data: { message: '父組件的值', count: 0 }, methods: { parentMethod () { console.log('我是父級的方法'); } } components: { childComponent } }) </script> 

1.3 使用修飾符.sync數組

修飾符.sync2.3.0+新增,它對props起到了一種修飾的做用,使用.sync進行修飾的props,意味着子組件有修改它的意圖,這種狀況下它只起到一個標註性做用,有它沒它都不會影響邏輯app

使用.sync修改上邊的代碼:ide

// 父組件 List.vue
<template> <!-- 這裏不寫 .sync 也不會影響結果 --> <List-item :title.sync="title" @update:title="updataTitle"></List-item> </template> <script> import ListItem from "./ListItem"; export default { data() { return { title: "我是title", } }, components: { ListItem }, methods: { updataTitle(res) { this.title = res; } } } </script> // 子組件 ListItem.vue <template> <div> <button @click="handleClick">Click me</button> <div>{{title}}</div> </div> </template> <script> export default { props: { title: String, }, methods: { handleClick() { // 子組件向父組件傳值 this.$emit('update:title', '我要父組件更新 title'); } } } </script> 

使用.sync向子組件傳遞多個props工具

當咱們用一個對象同時設置多個prop的時候,也能夠將這個.sync修飾符和v-bind配合使用:this

<text-document v-bind.sync="doc"></text-document> 

這樣會把doc對象中的每個屬性(如:title)都做爲一個獨立的prop傳進去,而後各自添加用於更新的v-on監聽器。spa

2、子組件向父組件傳值

2.1 經過事件傳值$emit

使用:

子組件使用$emit發送一個自定義事件

父組件使用指令v-on監聽子組件發送的事件

<div id="app"> <child-component @child-event="childEvent"></child-component> </div> <script> //子組件 const childComponent={ data:()=>({ msg:'點擊發送值到父組件', count:null }), methods:{ handleClick(data){ this.$emit('child-event','我是子組件傳過來的值'); } } template:`<div><p @click="handleClick">{{msg}}</p><p>{{count}}</p><div>` } // 父級 new Vue({ el:'#app', data:{ message:'父組件的值', count:0 }, methods:{ childEvent(data){ console.log("子組件傳過來的值",data); } } components:{ childComponent } }) </script> 

2.2 經過$children獲取子組件實例

$parent

2.3 經過ref註冊子組件引用

雖然存在prop和事件,可是有時仍可能須要在 JavaScript 裏直接訪問一個子組件。爲了實現這樣的需求,能夠使用ref特性爲某個子組件設置一個 ID 引用,就是一個身份標識

<div id="app"> <child-component ref="childComponent"></child-component> <button @click="getRefs"> 獲取子組件實例 </button> </div> <script> //子組件 const childComponent={ data:()=>({ msg:'點擊發送值到父組件', count:null }), template:`<div><p @click="handleClick">{{msg}}</p><p>{{count}}</p><div>` } // 父級 new Vue({ el:'#app', data:{ message:'父組件的值', count:0 }, methods:{ getRefs(){ console.log("子組件傳過來的值",this.$refs.childComponent.msg); } } components:{ childComponent } }) </script> 

3、兄弟組件傳值

3.1Bus中央事件總線

非父子組件傳值,能夠使用一個空的Vue實例做爲中央事件總線,結合實例方法$on$emit使用

注意:

註冊的Bus要在組件銷燬時卸載,不然會屢次掛載,形成觸發一次但多個響應的狀況。

beforeDestroy(){ this.$Bus.$off('方法名',value); } 

Bus定義方式:

  • 1,將Bus抽離出來,組件有須要時引入

    // bus.js import Vue from 'vue'; const Bus = new Vue(); export default Bus; 
  • 2,將Bus掛載到 Vue 根實例的原型上

    import Vue from 'vue'; Vue.prototype.$bus = new Vue(); 
  • 3,將Bus注入到 Vue 根對象上

    import Vue form 'vue'; const Bus = new Vue(); new Vue({ el:'#app', data:{ Bus } }) 

    使用例子:

    <div id="app"> <child-component ></child-component> <child-component-two ></child-component-two> </div> <script> Vue.prototype.$bus = new Vue(); //子組件1 const childComponent={ data:()=>({ msg:'我是子組件一', sendMsg:'我是子組件一發送的值' }), methods:{ handleClick(){ this.$Bus.$emit('sendMsg',this.sendMsg); } } template:`<div><p @click="handleClick">{{msg}}</p></p><div>` } //子組件2 const childComponentTwo={ data:()=>({ msg:'我是子組件二', brotherMsg:'' }), mounted(){ this.$Bus.$on('sendMsg',data=>{ this.brotherMsg = data; }) }, beforeDestroy(){ this.$Bus.$off('sendMsg'); } template:`<div><p @click="handleClick">{{msg}}</p><p>{{brotherMsg}}</p><div>` } // 父級 new Vue({ el:'#app', data:{}, components:{ childComponent, childComponentTwo } }) </script> 

4、跨組件

4.1$attrs$listeners

若是父組件 A 下面有子組件 B,組件 B 下面有組件 C,這時若是組件 A 直接想傳遞數據給 組件 C,那就行不通了!因此,這時能夠使用$attrs$listeners

Vue 2.4 提供了$attrs$listeners來實現可以直接讓 組件 A 傳遞消息給 組件 C

// 組件A Vue.component('A', { template: ` <div> <p>this is parent component!</p> <B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B> </div> `, data() { return { message: 'hello', messagec: 'hello c' //傳遞給c組件的數據 } }, methods: { // 執行B子組件觸發的事件 getChildData(val) { console.log(`這是來自B組件的數據:${val}`); }, // 執行C子組件觸發的事件 getCData(val) { console.log(`這是來自C組件的數據:${val}`); } } }); // 組件B Vue.component('B', { template: ` <div> <input type="text" v-model="mymessage" @input="passData(mymessage)"> <!-- C組件中能直接觸發 getCData 的緣由在於:B組件調用 C組件時,使用 v-on 綁定了 $listeners 屬性 --> <!-- 經過v-bind 綁定 $attrs 屬性,C組件能夠直接獲取到 A組件中傳遞下來的 props(除了 B組件中 props聲明的) --> <C v-bind="$attrs" v-on="$listeners"></C> </div> `, /** * 獲得父組件傳遞過來的數據 * 這裏的定義最好是寫成數據校驗的形式,省得獲得的數據是咱們意料以外的 * * props: { * message: { * type: String, * default: '' * } * } * */ props: ['message'], data () { return { mymessage: this.message } }, methods: { passData(val){ //觸發父組件中的事件 this.$emit('getChildData', val) } } }); // 組件C Vue.component('C', { template: ` <div> <input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)"> </div> `, methods: { passCData(val) { // 觸發父組件A中的事件 this.$emit('getCData',val) } } }); var app = new Vue({ el:'#app', template: ` <div> <A /> </div> ` }); 

4.2provideinject

熟悉 React 開發的同窗對 Context API 確定不會陌生吧!在 Vue 中也提供了相似的 API 用於組件之間的通訊。在父組件中經過provide來提供屬性,而後在子組件中經過inject來注入變量。不論子組件有多深,只要調用了inject,那麼就能夠注入在provide中提供的數據,而不是侷限於只能從當前父組件的prop屬性來獲取數據,只要在父組件的生命週期內,子組件均可以調用。這和 React 中的 Context API 有沒有很類似!

// 定義 parent 組件 Vue.component('parent', { template: ` <div> <p>this is parent component!</p> <child></child> </div> `, provide: { for:'test' }, data() { return { message: 'hello' } } }); // 定義 child 組件 Vue.component('child', { template: ` <div> <input type="tet" v-model="mymessage"> </div> `, inject: ['for'], // 獲得父組件傳遞過來的數據 data(){ return { mymessage: this.for } }, }); const app = new Vue({ el: '#app', template: ` <div> <parent /> </div> ` }); 

上面的實例中,定義了組件parent和組件child,組件parent和 組件child是父子關係。

  • parent組件中,經過provide屬性,以對象的形式向子孫組件暴露了一些屬性
  • child組件中,經過inject屬性注入了parent組件提供的數據,實際這些經過inject注入的屬性是掛載到 Vue 實例上的,因此在組件內部能夠經過this來訪問

注意:

官網文檔說起 provide 和 inject 主要爲高階插件 / 組件庫提供用例,並不推薦直接用於應用程序代碼中。

4.3 Vuex 狀態管理

Vuex 是狀態管理工具,實現了項目狀態的集中式管理。工具的實現借鑑了 Flux、Redux 和 The Elm Architecture 的模式和概念。固然與其餘模式不一樣的是,Vuex 是專門爲 Vue.js 設計的狀態管理庫,以利用 Vue.js 的細粒度數據響應機制來進行高效的狀態更新。

相關文章
相關標籤/搜索