⭐️ 更多前端技術和知識點,搜索訂閱號
JS 菌
訂閱css
除了使用 Vuex 方法外,vue 提供了各類各樣的組件間通訊的方案。文章整理一下父子組件、兄弟組件、祖前後代組件間是如何通訊的。 💬html
子組件有時須要與父組件進行溝通,溝通的方式就是子組件 emit 事件,父組件經過監聽這個事件來作進一步動做。而父組件與子組件通訊則使用 props前端
假設這裏有一個父組件並引入了一個子組件 my-comp:vue
<my-comp v-for="msg in msgs" :key="msg.id" :msg="msg"></my-comp>
複製代碼
父組件有一系列 msg 數據須要經過子組件渲染,將 msg 做爲 prop 傳遞給子組件便可:app
import MyComp from '@/components/MyComp.vue'
export default {
name: 'home',
components: {
MyComp
},
data () {
return {
msgs: [{
id: 1, data: 'hello js'
}, {
id: 2, data: 'css world'
}, {
id: 3, data: 'animated style'
}]
}
}
}
複製代碼
咱們經過點擊子組件每一項觸發一個事件,父組件監聽這個事件去動態改變子組件的 color 樣式,這就是父組件監聽子組件事件,事件處理函數能夠從子組件傳遞值給父組件:ide
<my-comp v-for="msg in msgs" :key="msg.id" :msg="msg" :colored="colored" @handle-change-color="handleChangeColor"></my-comp>
複製代碼
首先增長一個事件 handle-change-color 當這個事件被觸發時修更名爲 color 的 data,而後將 colored 經過 props 傳入到子組件:函數
import MyComp from '@/components/MyComp.vue'
export default {
name: 'home',
components: { // 註冊組件
MyComp
},
data () {
return {
colored: false, // 狀態
msgs: [{
id: 1, data: 'hello js'
}, {
id: 2, data: 'css world'
}, {
id: 3, data: 'animated style'
}]
}
},
methods: {
handleChangeColor () {
this.colored = !this.colored // 監聽事件動態改變 colored
}
// handleChangeColor (param) { // 子組件觸發的事件可能包含參數
}
}
複製代碼
而後編輯子組件:ui
<div>
<div @click="handleClick" :style="{color}">
{{msg.id}} - {{msg.data}} ⭕
</div>
</div>
複製代碼
首先渲染數據,並監聽 click 點擊事件,當點擊觸發事件處理函數 handleClickthis
export default {
name: 'MyComp',
computed: {
color () { // color 爲樣式
return this.colored ? 'red' : 'black' // 根據父組件傳入的 props 動態修改樣式
}
},
props: ['msg', 'colored'],
methods: {
handleClick (e) {
this.$emit('handle-change-color') // 使用 $emit 方法觸發父組件 handle-change-color 事件
// this.$emit('handler', 'param') // 還能夠給事件傳遞參數
}
}
}
複製代碼
子組件接收 colored 父組件傳遞來的 prop,返回一個計算後的屬性 color,根據 colored 返回不一樣樣式。handleClick 處理當子組件元素被點擊時 $emit
派發父組件的 handle-change-color 事件spa
效果以下:
使用 $children
操做子組件。如上述例子中,colored 被定義在父組件中,能夠將其移動到子組件中,並在父組件經過 $children
訪問到子組件:
<template>
<div @click="handleClick" class="home">
<my-comp v-for="msg in msgs" :key="msg.id" :msg="msg"></my-comp>
</div>
</template>
複製代碼
handleClick 事件被放置在 div 中
import MyComp from '@/components/MyComp.vue'
export default {
// ...
data () {
return {
msgs: [{
// ...
}]
}
},
methods: {
handleClick () {
this.$children.forEach(child => {
child.$data.colored = !child.$data.colored // 逐一控制子組件的 $data
})
}
}
}
複製代碼
在子組件中不須要 $emit
事件,只需維護一個 data:
export default {
name: 'MyComp',
data () {
return {
colored: false // colored 狀態
}
},
computed: {
color () {
return this.colored ? 'red' : 'black'
}
},
props: ['msg']
}
複製代碼
子組件可經過 $parent
來修改父組件的 $data
,所以 colored 定義在父組件中。
<template>
<div class="home">
<my-comp v-for="msg in msgs" :key="msg.id" :msg="msg" :colored="colored"></my-comp>
</div>
</template>
複製代碼
經過 prop 傳遞 colored 參數給子組件
import MyComp from '@/components/MyComp.vue'
export default {
name: 'home',
components: {
MyComp
},
data () {
return {
colored: false, // 父組件維護一個 colored 狀態
msgs: [{
// ...
}]
}
}
}
複製代碼
父組件定義 colored 狀態
<template>
<div>
<div @click="handleClick" :style="{color}">
{{msg.id}} - {{msg.data}} ⭕
</div>
</div>
</template>
複製代碼
子組件渲染 msg 並監聽 click 事件
export default {
// ...
props: ['msg', 'colored'],
methods: {
handleClick (e) {
this.$parent.$data.colored = !this.$parent.$data.colored
}
}
}
複製代碼
經過 $parent
訪問父組件,並修改 $data
狀態
咱們可使用使用中央事件總線來處理非父子組件間的通訊
具體步驟是建立一個 Vue 實例,而後 $on
監聽事件,$emit
來派發事件
// src/eventBus.js
import Vue from 'vue'
export default new Vue()
複製代碼
首先建立並導出一個 Vue 實例
import bus from '@/eventbus'
export default {
// ...
methods: {
handleClick (e) {
bus.$emit('change-color')
}
}
}
複製代碼
後代元素 $emit 觸發 eventBus 的事件
import bus from '@/eventbus'
export default {
// ...
mounted () {
bus.$on('change-color', () => {
this.colored = !this.colored
})
}
}
複製代碼
祖先元素 $on 方法監聽 eventBus 的事件
適用於祖先和後代關係的組件間的通訊,祖先元素經過 provide 提供一個值,後代元素則經過 inject 獲取到這個值。這個值默認是非響應的,若是是對象那麼則是響應式的:
export default {
name: 'home',
provide () {
return {
colored: this.colored // 依賴於 data
}
},
components: {
MyComp
},
data () {
return {
colored: { // 必須爲對象
value: false
},
msgs: [{
// ...
複製代碼
首先經過 provide 對外提供一個 colored,這個屬性依賴於 data 中的 colored,該變量必須爲一個對象,纔是響應式的。
⚠️ 必須爲一個對象
methods: {
handleChangeColor () {
this.colored.value = !this.colored.value
}
}
複製代碼
祖先組件監聽事件或其餘途徑去修改 data 改變狀態。
export default {
name: 'MyComp',
inject: ['colored'], // inject colored
computed: {
color () {
return this.colored.value ? 'red' : 'black' // do more...
}
},
// ...
複製代碼
後代組件經過 inject 獲取到祖先組件提供的對象,根據對象作進一步動做。
根據官方的文檔,咱們能夠經過 $root
來直接訪問到 Vue 實例
比方說將數據存儲在 Vue 實例中:
// src/main.js
new Vue({
data () {
return { // 在這裏!!
colored: false
}
},
router,
store,
render: h => h(App)
}).$mount('#app')
複製代碼
而後咱們在其餘各個組件中都可以使用:
export default {
name: 'MyComp',
// ...
mounted () {
console.log(this.$root) // 直接訪問到根組件
},
// ...
}
複製代碼
請關注個人訂閱號,不按期推送有關 JS 的技術文章,只談技術不談八卦 😊