天天看點

Vue 的響應式原則與雙向資料綁定

Vue 的響應式原則與雙向資料綁定

英文 | https://javascript.plainenglish.io/vues-reactive-principles-vs-two-way-data-binding-e741b995b0f7

使用 Vue.js 久了,還是不明白響應式原理和雙向資料綁定的差別?今天,我們就一起來學習一下,将解釋它們的差別。

反應性原則

它是 Vue.js 的核心特性之一,一個資料驅動的視圖,我們修改資料視圖來響應更新,非常優雅。

Vue2.x 使用 Object.defineProperty() 實作,而 Vue3.x 使用 Proxy 實作。 我們先來看看2.x的實作。

Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function getter () {
        return obj[key];
    },
    set: function setter (newVal) {
        ...
    } 
})      

我們通過Object.defineProperty給對象obj添加屬性,可以設定對象屬性的getter和setter函數。 

之後,我們每通過點文法擷取一個屬性,就會執行這裡的getter函數。 在這個函數中,我們會将調用這個屬性的依賴收集到一個集合中; 當我們給屬性指派時,這個定義就會被觸發。 setter函數,在輔助函數中,會通知集合中的依賴更新,讓資料變化驅動視圖變化。

3.x的核心思想和2.x一樣,隻是在資料劫持上使用了Proxy而不是Object.defineProperty,但是在處理數組和響應式處理新屬性時Proxy比Object.defineProperty更友善 .

let nObj=new Proxy(obj,{
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
})      

Vue響應式原理的實作細節相信大部分人已經很熟悉了,這裡不再贅述。

雙向資料綁定

雙向資料綁定通常是指我們使用的 v-model 指令的實作。 它是 Vue 的一個特性,也可以說是輸入事件和值的文法糖。 Vue 通過 v-model 指令為元件添加輸入事件處理和值屬性指派。

<template>
   <input v-model='localValue'/>
</template>      

上面的元件等價于下面的代碼。

<template>
   <input @input='onInput' :value='localValue' />
   <span>{{localValue}}</span>
</template>
<script>
  export default{
    data(){
      return {
        localValue:'',
      }
    },
    methods:{
      onInput(v){
         this.localValue=v.target.value;
         console.log(this.localValue)
      }
    }
  }
</script>      

是以,當我們修改輸入框的值時,我們通過v-model綁定的值也會同步修改。 基于以上原理,我們可以輕松實作一個雙向資料綁定元件。

v-model實踐

首先,我們定義一個Vue元件:

<tempalte>
  <div class="count" @click="addCount">click me {{value}}</div>
</template>
<script>
export default{
      props:{
        value:{
          type:Number,
          default:0
        }
      },
      watch:{
        value(v){
          this.localvalue=v;
        }  
      },
      methods:{
        addCount(){
           this.localvalue++;
           this.$emit('input',this.localvalue);
        }
      },
      data(){
        return{
          localvalue:0
        }
      },
      created(){
        this.localvalue=this.value;
      }
    }
</script>      

上面的元件指定我們在 props 中添加 value 屬性,并在 value 更新時觸發 input 事件。 在建立的 hook 和 watch 中對 localvalue 的指派是将父元件的狀态同步到子元件。

通過上面的元件定義,我們可以使用 v-model 指令對元件進行雙向資料綁定。

<template>
  <add-one v-model="count"></add-one>
  <span>The parent component{{count}}</span>
</tempalte>
<script>
export default{
  data() {
    return {
       count: 0,
    };
  },
  methods: {
  },
  created(){   
  }
}
</script>      

以下是實際效果。

Vue 的響應式原則與雙向資料綁定

當然,我們也可以不使用 value 和 input 事件的組合。 為了讓元件的定義更加語義化,我們還可以自定義屬性和事件,實作雙向綁定。 我們可以在元件的模型選項中設定值和事件。 如下:

export default{
  model:{
    value:'count',
    event:'change'
  },
  props:{
    count:{
      type:Number,
      default:0
    }
  },
  methods:{
    addCount(){
       this.localvalue++;
       this.$emit('change',this.localvalue);
    }
  },
}      

由上述元件定義。

<add-one v-model="count"></add-one>      

相當于:

<template>
   <add-one @change='onChange' :count='count'></add-one>
   <span>{{count}}</span>
</template>
<script>
  export default{
    data(){
      return {
        count:0,
      }
    },
    methods:{
      onChange(v){
         this.count=v;
         console.log(this.count)
      }
    }
  }
</script>      

隻是v-model指令幫我們做了上面的事件添加、屬性綁定和狀态同步操作。

最後

以上就是今天全部内容,謝謝你的閱讀。如果你覺得有用關注我,感謝感謝。

Vue 的響應式原則與雙向資料綁定