第一種,子組件通過監聽父組件數據,子組件改變數據之后通知給父組件
原文鏈接:https://blog.csdn.net/m0_37728716/article/details/81776929
父組件 => props[parent-data] => 子組件 => watch[parent-data] => children-data = parent-data // 子組件監聽父組件的改變
子組件 => $emit[children-data] => 父組件 => parant-data = children-data // 子組件通知父組件自身的改變
// 父組件 <template> <div> <Children :parentData="parentData" @getChildrenStatus="getChildrenStatus"></Children> </div> </template> <script> export default { data(){ return { parentData: 1 } }, methods: { getChildrenStatus: function(data){ // 實時更新子組件的變化 this.parentData = data } } } </script>
//子組件 <script> export default { data(){ return { chiildrenData: 1 } }, props: ['parentData'], watch: { parentData: function(){ // 監聽父組件的變化 this.childrenData = this.parentData } }, mounted(){ this.$emit('getChildrenStatus', this.childrenData) // 將改變通知父組件(保證父子組件數據一致) } } </script>
第二種 .sync 修飾符
在vue的組件通信props中,一般情況下,數據都是單向的,子組件不會更改父組件的值
那么vue提供.sync作為雙向傳遞的關鍵字,實現了父組件的變動會傳遞給子組件,而子組件的foo改變時,通過事件機制,修改父組件的foo。完成了子組件newFoo和父組件foo的雙向映射。
// 父組件 <Son :foo.sync="foo"></Son>
//子組件 props: ['foo'], data: function () { return { newFoo: this.foo; } }, methods:{ add:function(){ this.newMsg=10; this.$emit('update:foo',this.newFoo); } }
在一些情況下,可能會對一個props進行'雙向綁定',事實上 , '.sync'修飾符提供了此功能
- 當一個子組件改變了一個props 的值時,這個變化也會同步到父組件中所綁定的值
- 也會導致問題,因為破壞了‘單項數據流’的假設,由於子組件改變props的代碼和普通代碼改懂毫無區別,當光看子組件代碼時,完全不知何時改變了父組件的狀態
- 會被重新引入,擴展為一個自動更新父組件屬性的v-on偵聽器
- v-model畢竟不是給組件與組件之間通信而設計的雙向綁定,無論從語意上和代碼寫法上都沒有,'.sync'直觀和方便
- 無論從v-model還是'.sync'修飾符來看,都離不開$emit 和 v-on 語法糖的封裝,主要目的還是為了保證數據的正確單向流動與顯示流動
<Son :foo.sync="sth"></Son> //.sync修飾符 <Son :foo="sth" @update:foo="value=>sth=value"></Son>
- :foo則是Son 子組件需要從父組件props接受的數據
- 通過事件顯示監聽update:foo(foo則是props顯示監聽的數據),通過箭頭函數執行回調,把函數傳給sth,則就形成一種雙向綁定循環鏈條
- 當子組件需要更新foo的值時,需顯示地觸發更新事件
this.$emit('update:foo',newValue)
同時父組件@update:foo 也是依賴子組件的顯示觸發,這樣可以輕松的捕捉到了數據的正常流動
- 第一個參數則是 update 則是顯示更新的事件,跟在后面的 :foo 則是需要改變對應的props值
- 第二個參數傳入的是希望父組件foo數據里將要變化的值,以及用於父組件接受update時更新數據
warn: 子組件改變父組件的數據時,update冒號后面的參數和父組件傳遞進來的值是同步的,想改變哪個,則冒號后面的值對應的就是哪個,兩者相互對應,必填