1. 程式人生 > 程式設計 >詳解vue父子元件狀態同步的最佳方式

詳解vue父子元件狀態同步的最佳方式

哈嘍!大家好!我是木瓜太香,一位老牌兒前端工程師,平時我們在使用 vue 開發的時候,可能會遇到需要父元件與子元件某個狀態需要同步的情況,通常這個是因為我們封裝元件的時候有一個相同的狀態外面要用,裡面也要用,今天我們就來看看怎麼優雅的解決這個問題吧!
一般來說我們實現這個功能,只需要父元件通過 props 傳遞給子元件就好了,但是理想很豐滿,現實很骨感,如果我們直接在子元件更改傳進來的 props ,不出意外瀏覽器會給你一坨大紅色的報錯,因為在 vue 中我們的資料流動是自上而下的,而子元件直接更改父元件傳來的 props 則是自下而上的資料流動,這是 vue 不允許的。

所以通常我們的解決辦法是,父元件通過 props 傳入狀態給子元件,子元件通過 props 來初始化另外一個內部的狀態,子元件每次更改狀態之後都通知父元件,然後由父元件來更改自己的狀態,其實就是 props on emit 的應用,接下來我們來上程式碼。

父元件 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>

好了,兩種寫法我們都已經演示完畢,現在我們來優化一下父元件中的寫法。

父元件中可以看到我們之前在上面綁定了一個 update:food 事件,並且使用箭頭函式做了一個賦值,其實這裡我們可以稍微優化一下,不要箭頭函式直接賦值,因為我們觸發的是自定義事件,而我們觸發的時候給的第一個引數就是新值,我們可以直接通過 $event 拿到這個值,所以可以寫成如下形式:

優化後的父元件

<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 就不合適了。

到此這篇關於詳解vue父子元件狀態同步的最佳方式的文章就介紹到這了,更多相關vue父子元件狀態同步 內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!