在Vue2.X中孝凌,父子組件之間有兩點(diǎn)非常重要的通信原則:
-
父子組件是單向數(shù)據(jù)流,父組件的狀態(tài)更新蛔琅,子組件中prop的狀態(tài)也會(huì)更新胎许,但是子組件的狀態(tài)變化不會(huì)影響父組件峻呛。在子組件中修改prop的狀態(tài)罗售,會(huì)在console中報(bào)錯(cuò)。關(guān)于單向數(shù)據(jù)流钩述,Vue文檔中是這樣來描述原因的:
這是為了防止子組件無意間修改了父組件的狀態(tài)寨躁,來避免應(yīng)用的數(shù)據(jù)流變得難以理解。
有一點(diǎn)應(yīng)該注意牙勘,如果父組件傳遞給子組件的狀態(tài)是
對(duì)象
或者數(shù)組
职恳,因?yàn)閮烧呤前匆脗髦担栽谧咏M件中是可以改變對(duì)象和數(shù)組中的值的方面,同時(shí)也會(huì)影響到父組件的狀態(tài)放钦。 每次父組件狀態(tài)更新時(shí),父組件的所有雙向綁定的model都會(huì)進(jìn)行更新恭金;同時(shí)操禀,子組件的所有 prop 也會(huì)進(jìn)行更新。這里要注意横腿,父組件中更新的狀態(tài)颓屑,必須在父組件中進(jìn)行了雙向綁定,或者傳遞到了子組件耿焊,才會(huì)觸發(fā)父組件的其他狀態(tài)的更新揪惦。
如果希望在子組件中改變父組件的狀態(tài),有兩種方式:
- 其一是通過事件派發(fā)罗侯,父組件響應(yīng)子組件派發(fā)的事件器腋,由父組件自己改變自己的狀態(tài)
- 其二是父組件向子組件傳遞
數(shù)組
或者對(duì)象
,在子組件中改變數(shù)組
或者對(duì)象
的狀態(tài)
因?yàn)閂ue的雙向數(shù)據(jù)綁定是基于Object.defineProperty()
來劫持屬性的setter
和getter
方法,由于js的限制纫塌,如果某一個(gè)組件的狀態(tài)是一個(gè)數(shù)組再愈,對(duì)數(shù)組的修改無法通過Object.defineProperty()
劫持到,所以無法把狀態(tài)的更新反饋到視圖上护戳。舉一個(gè)例子翎冲,下面是一個(gè)Vue單文件組件,當(dāng)我點(diǎn)擊按鈕的時(shí)候媳荒,視圖無法更新抗悍。
<template>
<div id="header-ctn">
hello {{msg[0]}}
<button @click="change">點(diǎn)我改變組件狀態(tài)</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: ['yanbin', 'bluestrings']
}
},
mounted () {
},
methods: {
change () {
this.msg[0] = '閆斌';//應(yīng)該寫成 this.$set(this.msg, 0, "閆斌");
}
}
}
</script>
所以Vue提供了操作數(shù)組的方法來解決這個(gè)問題:
Vue.set(array, pos, newVal);
但是在很多實(shí)際的case中,即使沒有用Vue.set這個(gè)方法來操作數(shù)組钳枕,我們發(fā)現(xiàn)數(shù)組的變化依然反饋到了視圖上缴渊,這是什么原因呢?這里就要提到剛才說到的一點(diǎn)鱼炒,如果當(dāng)前組件的某一個(gè)狀態(tài)發(fā)生更新衔沼,Vue會(huì)強(qiáng)制自動(dòng)刷新其他綁定的狀態(tài),也就是說組件狀態(tài)反饋到視圖上的這個(gè)操作是Vue自動(dòng)執(zhí)行的昔瞧,而不再是通過Object.defineProperty()
來劫持的指蚁。拿剛才的例子修改一下:
<template>
<div id="header-ctn">
hello {{msg[0]}}<br/>
今天{{day}}
<button @click="change">點(diǎn)我改變組件狀態(tài)</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: ['yanbin', 'bluestrings'],
day: '星期天'
}
},
mounted () {
},
methods: {
change () {
this.msg[0] = '閆斌';
this.day = '星期一';
}
}
}
</script>
<style lang="less">
</style>
因?yàn)樾薷牧私M件的狀態(tài)day
,所以Vue將msg這個(gè)數(shù)組的更新也反饋到了視圖上自晰。