Vue2 利用 v-model 實現元件props雙向繫結的優美解決方案

十年發表於2017-03-12

在專案中開始使用vue2來構建專案了,跟 vue1 很大的一處不同在於2 取消了props 的雙向繫結,改成只能從父級傳到子級的單向資料流,初衷當然是好的,為了避免雙向繫結在專案中容易造成的資料混亂。

解決方案一

然後開始參考網上和github上的方案等等,發現很多解決方案是這樣的

  1. 用data物件中建立一個props屬性的副本

  2. watch props屬性 賦予data副本 來同步元件外對props的修改

  3. watch data副本,emit一個函式 通知到元件外

這裡以最常見的 modal為例子:
modal挺合適雙向繫結的,外部可以控制元件的 顯示或者隱藏,元件內部的關閉可以控制 visible屬性隱藏,同時visible 屬性同步傳輸到外部


///modal.vue  元件
<template>
  <div class="modal" v-show="visible">
      <div class="close" @click="cancel">X</div>
  </div>
</template>

<script>
export default {
    name:`modal`,
    props: {
      value: {
        type: Boolean,
        default:false
      }
    },

  data () {
    return {
      visible:false
    }
  },
  watch:{
      value(val) {
        console.log(val);
        this.visible = val;
      },
      visible(val) {
        this.$emit("visible-change",val);
      }
  },
  methods:{
    cancel(){
      this.visible = false;
    }
  },
  mounted() {
    if (this.value) {
      this.visible = true;
    }
  }
}
</script>


///呼叫modal元件
<modal :value="isShow" @visible-change="modalVisibleChange"></modal>

export default {
  name: `app`,
  data () {
    return {
      isShow:true,
    }
  },
  methods:{
     modalVisibleChange(val){
       this.isShow = val;
     }
  }
}

這樣就解決了 元件props 雙向繫結的問題。 但是這樣有一個不是太美觀的現象就是 在父級呼叫 modal元件的時候,還需要寫一個 modalVisibleChange 的methods. 總是顯得這部分程式碼是多餘的。 特別是寫一個讓別人用的公共元件,這樣呼叫太麻煩了。
能不能不寫method來實現props的雙向繫結呢,答案是可以的。

優美解決方案

那就是利用 v-model, 然後使用value來儲存v-model的值,進行雙向繫結

改成如下程式碼:

<template>
  <div class="modal" :value="value" v-show="visible">
      <div class="close" @click="cancel">X</div>
  </div>
</template>

<script>
export default {
    props: {
      value: {
        type: Boolean,
        default:false
      }
    },

  data () {
    return {
      visible:false
    }
  },
  watch:{
      value(val) {
        console.log(val);
        this.visible = val;
      },
      visible(val) {
        this.$emit(`input`, val);
      }
  },
  methods:{
    cancel(){
      this.visible = false;
    }
  },
  mounted() {
    if (this.value) {
      this.visible = true;
    }
  }
}
</script>


///呼叫modal元件

  <modal v-model="isShow"></modal>

export default {
  name: `app`,
  data () {
    return {
      isShow:false
    }
  }
}
</script>

這樣呼叫元件的程式碼是不是很簡潔,其他人員要呼叫的話,會很輕鬆,只要設定 isShow 就可以控制 modal 元件的顯示或者隱藏,同時 如果是modal 元件內部關閉按鈕關閉的,狀態也會傳到 isShow

相關文章