Vue的兩種常見通信方式,你了解嗎?
vue組件化開發(fā)是一個非常美妙的過程,因為減少了代碼之間的耦合度,提高了復用性,直接就是我們開發(fā)人員的福音。
但是組件歸組件,組件之間也有幾種不同的關系,不同的關系要有對應的通信方法才是道理,比如組件之間關系圖就像是下面的一樣,組件還不止這些,那這些復雜的組件通信應該怎么處理呢?
接下來我將介紹一下vue常見的兩種種組件通信方式。
父子通信「props / $emit」
父傳子
我想從父組件傳一個數(shù)據(jù)給子組件,也就是上圖的從app組件傳到A組件,我可以先在App.vue組件定義一個數(shù)組,然后通過v-bind的方式綁定到子組件。
<template>
<div id="app">
<Child :ancient='ancient'/>
</div>
</template>
<script>
import Child from './views/Child.vue'
export default {
data () {
return {
ancient: ['床前明月光', '疑似地上霜', '舉頭望明月', '低頭思故鄉(xiāng)']
}
},
methods: {
},
components: {
Child
}
}
</script>
然后再在子組件通過props接收,然后循環(huán)渲染上去就好啦!
<template>
<div>
<ul>
<h2>靜夜思</h2>
<h4>李白</h4>
<li v-for="item in ancient" :key="item">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
props: {
ancient: {
type: Array,
required: true
}
},
data () {
return {
demoList: [111, 222, 333]
}
}
}
</script>
瀏覽器效果:
子傳父
想在子組件傳參數(shù)給父組件,首先我們在子組件創(chuàng)建一個點擊事件,然后我們通過點擊觸發(fā)$emit事件將想要傳遞的值發(fā)送過去。
<template>
<div>
<input type="text" v-model="myText">
<button @click="handleClick">提交</button>
</div>
</template>
<script>
export default {
data () {
return {
myText: '請寫出你的計劃'
}
},
methods: {
handleClick () {
console.log(this.myText)
this.$emit('setMessage', this.myText)
this.myText = ''
}
}
}
</script>
然后我們在父組件通過on監(jiān)聽子組件的事件并接收傳遞過來的值然后再觸發(fā)這邊的事件,從而達到子傳父的目的。
<template>
<div id="app">
<Child v-on:setMessage="getMessage"/>
<ul>
<li v-for="item in demoList" :key="item">{{item}}</li>
</ul>
</div>
</template>
<script>
import Child from './views/Child.vue'
export default {
data () {
return {
demoList: ['計劃1', '計劃2', '計劃3']
}
},
methods: {
getMessage (text) {
this.demoList.push(text)
}
},
components: {
Child
}
}
</script>
瀏覽器如下表示:
兄弟通信
兄弟通信比較推薦用bus通信,因為可以直接兩個組件之間互相通信從而省去了子傳父再傳子兩個步驟。
首先先聲明一輛bus,也就是在一個合適的地方創(chuàng)建一個EvenBus.js,然后內部如下:
import Vue from 'vue'
const eventBus = new Vue()
export default eventBus
然后有人可能會疑惑為什么要這樣引入vue實例。先帶著這個疑問繼續(xù)看下去。
然后我將兩個組件放在App組件內,分別是BroderB.vue和BroderD.vue。
APP.vue
<template>
<div id="app">
<BorderB />
<BorderD />
</div>
</template>
<script>
import BorderB from './views/BroderB.vue'
import BorderD from './views/BroderD.vue'
export default {
data () {
return {
}
},
methods: {
},
components: {
BorderB,
BorderD
}
}
</script>
然后我們先看BroderB.vue
<template>
<div>
<input type="text" v-model="myText">
<button @click="handleClick">提交</button>
</div>
</template>
<script>
import evenBus from '../util/EvenBus'
export default {
data () {
return {
myText: ''
}
},
methods: {
handleClick () {
evenBus.$emit('setMessage', this.myText)
}
}
}
</script>
我這里引入了EvenBus,然后通過點擊事件觸發(fā)事件,然后這里回應為什么要實例,因為每個實例都有emit 方法,當然也有監(jiān)聽 $on 方法。然后傳遞這個事件和值出去。
然后再在BroderD.vue接收
<template>
<div>
<h1 v-for="item in demoList" :key="item">{{item}}</h1>
</div>
</template>
<script>
import evenBus from '../util/EvenBus'
export default {
data () {
return {
demoList: ['111', '222', '333']
}
},
methods: {
handleGet (msg) {
this.demoList.push(msg)
}
},
mounted () {
evenBus.$on('setMessage', this.handleGet)
},
beforeDestroy () {
evenBus.$off('setMessage', this.handleGet)
}
}
</script>
在這個組件的mounted鉤子函數(shù)中監(jiān)聽這個$on事件,并觸發(fā)這里的方法,從而讓兩個組件產(chǎn)生通信,然后就是這里的方法接收值并使用值了
然后也有人會問,為什么后面還有一個beforeDestroy的鉤子函數(shù),那肯定是有作作用的,當我們結束這個組件的時候最好就是讓這個evenBus解綁,因為如果在項目中的話,可能會存在某些奇奇怪怪的問題。
然后我們看瀏覽器如下