Vue父子組件通信實踐
組件(Component)是Vue.js的核心部分,組件的作用域是孤立的,所以不能在子組件模板內直接引用父組件的數據,但是組件之間的通信是必不可少的。組件A在其模板中使用了組件B,A組件要向B組件傳遞數據,B組件要將其內部發生的事情告知A組件,那麽A、B組件怎麽進行通信呢?
Vue.js父子組件的關系可以總結為props down,events up,父組件通過props向下傳遞數據給子組件,子組件通過events給父組件發送消息,它們的工作方式如下圖所示:
父組件 - 子組件:父組件傳值給子組件使用Props屬性。
子組件 - 父組件:子組件傳值給父組件使用Emit事件。
1. 父組件通知子組件
props是父組件用來向子組件傳遞數據的一個自定義屬性,子組件需要顯示的用props屬性聲明要傳遞的參數。
父組件向子組件index-header傳遞showDate參數。
1 |
< index-header :showDate = "showDate" ></ index-header >
|
1 2 3 4 5 6 7 8 9 10 |
export default {
data() {
return {
showDate: true
}
},
components: {
‘indexHeader‘ : IndexHeader
}
}
|
子組件配置showDate參數。
1 2 3 |
export default {
props: [ ‘showDate‘ ]
}
|
props是單向綁定的,當父組件的showDate屬性變化時,會傳遞給子組件,但是不會反過來,防止子組件無意修改父組件的狀態。每次父組件更新時,子組件所有的props參數都會異步更新為最新值。
由於子組件的props參數值是異步更新的,所以在子組件methods裏使用props參數要註意參數值是否是最新值。最近開發遇到一個問題,主組件傳值給子組件並調用子組件的方法,方法裏有用到props的參數值,每次調用方法裏的props參數值都是上一次的值,就是因為props異步更新導致的,可以采用下面兩種方法解決:
① 使用$nextTick,在數據變化之後等待 Vue 完成更新 DOM
父組件向子組件傳遞filterParam參數,並調用子組件的getDimData()方法,參數如果是駝峰的形式,才傳參時需要改為‘‘-‘’的方式。
1 |
< channel ref = "child" :filter-param = "filterParam" ></ channel >
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
export default {
data() {
return {
filterParam: {}
}
},
components: {
‘channel‘ : Channel
},
methods: {
getFilterParam(filterParam) {
this .filterParam = filterParam;
this .$nextTick(() => {
this .$refs.child.getDimData();
});
}
}
}
|
子組件配置filterParam參數,並在getDimData()方法中使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
export default {
props: [
‘filterParam‘
],
methods: {
getDimData() {
let param = {
"date: this.filterParam.filterTimeCur,
" channelCur": this .filterParam.ChannelCur
};
console..log(param);
}
}
|
② 監聽參數變化
父組件向子組件傳遞filterParam參數,並調用子組件的getDimData()方法。
1 |
< channel ref = "child" :filter-param = "filterParam" ></ channel >
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export default {
data() {
return {
filterParam: {}
}
},
components: {
‘channel‘ : Channel
},
methods: {
getFilterParam(filterParam) {
this .filterParam = filterParam;
}
}
}
|
子組件監聽filterParam的變化。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
export default {
props: [
‘filterParam‘
],
watch: {
filterParam() {
let param = {
"date: this.filterParam.filterTimeCur,
" channelCur": this .filterParam.ChannelCur
};
console..log(param);
}
}
|
2. 子組件通知父組件
子組件通過$emit自定義事件通知父組件,父組件通過v-on來監聽子組件觸發的事件,代碼實例如下:
父組件監聽子組件傳遞參數getFilterParam。
1 |
< index-header v-on:filterParam = "getFilterParam" :showDate = "showDate" ></ index-header >
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
export default {
data() {
return {
filterParam: {},
showDate: true ,
}
},
components: {
‘channel‘ : Channel
},
methods: {
getFilterParam(filterParam) {
this .filterParam = filterParam;
this .$nextTick(() => {
this .$refs.child.getDimData();
});
}
}
}
|
子組件向父組件傳遞參數filterParam。
1 2 3 4 5 6 7 8 9 10 11 |
export default {
data() {
dateCur: ‘today‘ ,
filterMainCur: ‘channel‘ ,
},
methods: {
this .$emit( ‘filterParam‘ , {
filterTimeCur: this .dateCur,
filterMainCur: this .filterMainCur
});
}
|
Reference:
Vue父子組件通信實踐