父組件 → 子組件
組件實例的作用域都是孤立的,也就是子組件在模板 template 不能引用父組件的數(shù)據(jù),那么,當子組件有需要使用父組件的時候,我們該怎么辦呢?
這里我們使用的是組件的 props 選項來聲明它想要得到的數(shù)據(jù)。
首先創(chuàng)建一個 vue 實例:
<div id="app"></div>
<script>
const app = new Vue({
el: '#app',
data: {
msg: '我是父組件的數(shù)據(jù)'
}
})
</script>
實例 app 中含有數(shù)據(jù) msg 值為“我是父組件的數(shù)據(jù)”,待會我們把它傳遞給子組件。
子組件還沒有注冊,接下來,我們就注冊一個組件,組件名為 son。
<div id="app">
<son></son>
</div>
Vue.component('son', {
template: `<div></div>`
})
子組件準備好了,下一步就開始傳遞數(shù)據(jù),父組件向子組件傳遞參數(shù),我們說過,用組件提供的 props 選項,接下來,我們就把父組件的 msg 傳給 子組件,并展示在頁面上。
上面代碼稍加修改:
<div id="app">
<son :message="msg"></son>
</div>
Vue.component('son', {
props: ['message'],
template: `<div>{{ message }}</div>`
})
效果如下:
注意:props 是單向綁定的(父→子),是 vue 為了防止子組件無意修改了父組件得數(shù)據(jù)和狀態(tài),如果多個子組件任意地對父組件進行修改,這會讓整個應用得數(shù)據(jù)流難以閱讀。
如果你想要修改父組件傳過來得數(shù)據(jù),最好是定義一個局部的變量,來依賴傳過來的數(shù)據(jù)。
子組件 → 父組件
相比父→子組件通信,子→父組件就稍微繁瑣一點,我們會使用到組件的一個知識點:自定義事件。
每一個 vue 實例都實現(xiàn)了事件接口,我們可以用它提供的 API $emit(eventName) 來觸發(fā)一個事件。
首先注冊一個新組件:
Vue.component('son', {
template: `<button @click="send">
點擊
</button>`,
methods: {
send() {
this.$emit('connect')
}
}
})
很簡單的一個組件,就是一個按鈕 button,點擊它的時候,會觸發(fā)組件內(nèi)部的 send() 方法,而方法里面會觸發(fā)一個事件,事件名取為:connect
然后我們就去父組件監(jiān)聽這個事件“connect”,監(jiān)聽方式跟普通原生的事件一模一樣,也是用 v-on 指令,縮寫用 @ 符號。我們采用縮寫來監(jiān)聽:
<div id="app">
<son @connect="say"></son>
</div>
我們設置了事件 connect 觸發(fā)的處理程序是一個 say() 方法,我們補上 say() 方法的定義:
const app = new Vue({
el: '#app',
methods: {
say() {
console.log('大家好,我監(jiān)聽到了事件connect的觸發(fā)')
}
}
})
我們在 say() 方法觸發(fā)的時候,在控制臺打印一句話,表示我們自定義的事件 connect() 成功觸發(fā),并被父組件監(jiān)聽到了。
效果如下:
接下來就是把子組件的數(shù)據(jù)傳遞給父組件。
Vue.component('son', {
template: `<button @click="send">點擊</button>`,
data() {
return {
msg: '大家好,我是子組件的數(shù)據(jù)'
}
},
methods: {
send() {
this.$emit('connect', this.msg)
}
}
})
我們把子組件的 data 中的 msg,通過 $emit() 一并發(fā)射出來,在父組件的 say() 方法接受即可。
methods: {
say(msg) {
console.log(msg)
}
}
效果如下:
非父子組件通信
除了父子組件的相互通信,非父子關系的組件該如何通信,我們可以巧妙 地利用一個空的 vue 實例來作為一個中央事件總線。
但是在事件開發(fā)中,我們不會這么做,我們會使用專門用于狀態(tài)管理的 vuex,vuex 的學習我們在后面學習。