首頁 > 軟體

Vue響應式原理及雙向資料繫結範例分析

2022-07-19 18:00:58

前言

之前公司招人,面試了一些的前端同學,因為公司使用的前端技術是Vue,所以免不了問到其響應式原理和Vue的雙向資料繫結。但是這邊面試到的80%的同學會把兩者搞混,通常我要是先問響應式原理再問雙向資料繫結原理,來面試的同學大都會認為是一回事,那麼這裡我們就說一下二者的區別。

響應式原理

是Vue的核心特性之一,資料驅動檢視,我們修改資料檢視隨之響應更新,就很優雅~

Vue2.x是藉助Object.defineProperty()實現的,而Vue3.x是藉助Proxy實現的,下面我們先來看一下2.x的實現。

Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    //攔截get,當我們存取data.key時會被這個方法攔截到
    get: function getter () {
        //我們在這裡收集依賴
        return obj[key];
    },
    //攔截set,當我們為data.key賦值時會被這個方法攔截到
    set: function setter (newVal) {
        //當資料變更時,通知依賴項變更UI
    } 
})

我們通過Object.defineProperty為物件obj新增屬性,可以設定物件屬性的gettersetter函數。之後我們每次通過點語法獲取屬性都會執行這裡的getter函數,在這個函數中我們會把呼叫此屬性的依賴收集到一個集合中 ;而在我們給屬性賦值(修改屬性)時,會觸發這裡定義的setter函數,在次函數中會去通知集合中的依賴更新,做到資料變更驅動檢視變更。

3.x的與2.x的核心思想一致,只不過資料的劫持使用Proxy而不是Object.defineProperty,只不過Proxy相比Object.defineProperty在處理陣列和新增屬性的響應式處理上更加方便。

let nObj=new Proxy(obj,{
  //攔截get,當我們存取nObj.key時會被這個方法攔截到
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  //攔截set,當我們為nObj.key賦值時會被這個方法攔截到
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
})

Proxy的詳細使用方法參考ES6教學

Vue的響應式原理的實現細節相信大多數同學已經很熟悉了,這裡就不在展開細談了,如果還想更詳細的瞭解,或者想要做一個簡易的Vue實現,可以參考這篇Vue原理,相信你會有不小收穫。

雙向資料繫結

雙向資料繫結通常是指我們使用的v-model指令的實現,是Vue的一個特性,也可以說是一個input事件和value的語法糖。 Vue通過v-model指令為元件新增上input事件處理和value屬性的賦值。

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

上述的元件就相當於如下程式碼

<template>
   <!-- 這裡新增了input時間的監聽和value的屬性繫結 -->
   <input @input='onInput' :value='localValue' />
   <span>{{localValue}}</span>
</template>
<script>
  export default{
    data(){
      return {
        localValue:'',
      }
    },
    methods:{
      onInput(v){
         //在input事件的處理常式中更新value的繫結值
         this.localValue=v.target.value;
         console.log(this.localValue)
      }
    }
  }
</script>
    <template>
      <div>
        <input @input='onInput' :value='localValue' />
        <span>{{localValue}}</span>
      </div>
    </template>
    <script>
    // import Vue from 'vue';
    export default{
      data(){
        return {
          localValue:'hello',
        }
      },
      methods:{
        onInput(v){
          this.localValue=v.target.value;
          console.log(this.localValue)
        }
      }
    }
    </script>
    <style>
    .count {
      color: red;
    }
    </style>

因此當我們修改input輸入框中的值時,我們通過v-model繫結的值也會同步修改,基於上述原理,我們可以很容易的實現一個資料雙向繫結的元件。

v-model實踐

首先我們定義一個Vue元件,相信大家已經很熟悉了。

<tempalte>
  <div class="count" @click="addCount">click me {{value}}</div>
</template>
<script>
export default{
      props:{
       //關鍵的第一步:設定一個value屬性
        value:{
          type:Number,
          default:0
        }
      },
      watch:{
        //監聽value變化,更新元件localvalue狀態
        value(v){
          this.localvalue=v;
        }  
      },
      methods:{
        //關鍵的第二步:事件觸發localvalue變更,通過事件同步父元件狀態變更
        addCount(){
           this.localvalue++;
           this.$emit('input',this.localvalue);
        }
      },
      data(){
        return{
          //元件狀態,遵守單項資料流原則,不直接修改props中的屬性
          localvalue:0
        }
      },
      created(){
        //初始化獲取value值
        this.localvalue=this.value;
      }
    }
</script>

上面的元件定了我們通過在props中新增value屬性,並且在值更新時觸發input事件。created勾點和watch中為localvalue賦值是為了同步父元件狀態到子元件中。
通過上面


IT145.com E-mail:sddin#qq.com