哈嘍!你們好!我是木瓜太香,一位老牌兒前端工程師,平時咱們在使用 vue 開發的時候,可能會遇到須要父組件與子組件某個狀態須要同步的狀況,一般這個是由於咱們封裝組件的時候有一個相同的狀態外面要用,裏面也要用,今天咱們就來看看怎麼優雅的解決這個問題吧!前端
通常來講咱們實現這個功能,只須要父組件經過 props
傳遞給子組件就行了,可是理想很豐滿,現實很骨感,若是咱們直接在子組件更改傳進來的 props
,不出意外瀏覽器會給你一坨大紅色的報錯,由於在 vue 中咱們的數據流動是自上而下的,而子組件直接更改父組件傳來的 props
則是自下而上的數據流動,這是 vue 不容許的。vue
因此一般咱們的解決辦法是,父組件經過 props 傳入狀態給子組件,子組件經過 props 來初始化另一個內部的狀態,子組件每次更改狀態以後都通知父組件,而後由父組件來更改本身的狀態,其實就是 props on emit 的應用,接下來咱們來上代碼。web
父組件 Father.vue瀏覽器
<template> <div class="father"> <h1>父組件維護的狀態:{{food}}</h1> <son :food="food" @update:food="f => food = f"></son> </div> </template>
子組件 Son.vue前端工程師
<template> <div class="son"> <h2>子組件中維護的狀態:{{innerFood}}</h2> <button @click="innerFood = '100斤牛肉'">點擊更改子組件狀態</button> </div> </template> <script> export default { data () { return { innerFood: this.food } }, props: { food: String }, watch: { innerFood (nv) { this.$emit("update:food",nv) } } } </script>
能夠看到咱們上述的寫法,實際上是維護了父子組件中的不一樣的兩個狀態,咱們作的工做只是將這兩個狀態同步了,這種寫法沒有任何問題,其實對於子組件的部分咱們也能夠經過 computed 來實現,下面咱們來看一看另外一種子組件內維護同步狀態的方法:函數
子組件 Son.vue 的另外一種寫法優化
<template> <div class="son"> <h2>子組件中維護的狀態:{{innerFood}}</h2> <button @click="innerFood = '100斤牛肉'">點擊更改子組件狀態</button> </div> </template> <script> export default { props: { food: String }, computed: { innerFood: { get () { return this.food }, set (nv) { this.$emit("update:food",nv) } } } } </script>
好了,兩種寫法咱們都已經演示完畢,如今咱們來優化一下父組件中的寫法。this
父組件中能夠看到咱們以前在上面綁定了一個 update:food
事件,而且使用箭頭函數作了一個賦值,其實這裏咱們能夠稍微優化一下,不要箭頭函數直接賦值,由於咱們觸發的是自定義事件,而咱們觸發的時候給的第一個參數就是新值,咱們能夠直接經過 $event
拿到這個值,因此能夠寫成以下形式:code
優化後的父組件事件
<template> <div class="father"> <h1>父組件維護的狀態:{{food}}</h1> <son :food="food" @update:food="food = $event"></son> </div> </template>
到這裏你覺得就結束了?其實咱們還能夠更近一步,只要知足咱們以上的事件命名方式,咱們實際上可使用 sync
修飾符代替事件的綁定,也就是咱們不用寫事件綁定了,可是子組件內部的事件觸發依然不能少,最終優化的結果以下:
<template> <div class="father"> <h1>父組件維護的狀態:{{food}}</h1> <son :food.sync="food"></son> </div> </template>
到此咱們就真的完成了父子組件的同步,固然在子組件中維護一個狀態不必定是必須的,若是咱們只用父組件傳給咱們的 props
作展現,而子組件沒有對這個 props
直接更改的行爲,那麼咱們就不用在子組件建立另一個狀態,咱們子組件想改他的時候只須要在合適的時機提交合適的事件便可,可是有一種狀況咱們不得不在子組件中建立另外一個狀態,就是咱們父組件傳入的狀態在子組件中用於 v-model 這種雙向數據綁定的功能時,因爲 v-model 會自動更改值因此直接填入從父組件接受的 props 就不合適了。
我本身建了一個web前端的交流裙有興趣的能夠加入進來交流哦:237871108。固然你也能夠經過嗶哩嗶哩搜索木瓜太香找到我。