首頁 > web前端 > Vue.js > 主體

解析vue中observer資料雙向綁定原理(程式碼分享)

奋力向前
發布: 2021-08-24 10:18:13
轉載
1910 人瀏覽過

之前的文章《淺析JS中Array物件一些操作方法(附程式碼)》中,給大家了解了JS中Array物件一些操作方法。以下這篇文章給大家了解vue中observer資料雙向綁定原理,夥伴們來看看。

解析vue中observer資料雙向綁定原理(程式碼分享)

vue資料雙向綁定原則與簡單的實作

解析vue中observer資料雙向綁定原理(程式碼分享)

1 )vue資料雙向綁定原理-observer

2)vue資料雙向綁定原理-wather

3)vue數據雙向綁定原理-解析器Complie

vue資料雙向綁定原理, 和簡單的實現

去他喵的底層原理,框架內核,老夫寫程式只用Jquery

個人覺得,不論是否是長期與之交集,還是應該看下核心的東西。多多了解高人是如何實現的,這樣才能學到更多的知識,才能成長進步。倘若某天被人問起,某種框架內褲,其實現原理,那麼只能是一臉懵逼了。

實作資料綁定的做法有大致如下幾種:

  • 發布者-訂閱者模式(backbone.js

  • 髒值檢查(angular.js

  • #資料劫持(vue.js

vue.js則是採用資料劫持結合發布者-訂閱者模式的方式,透過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時發布訊息給訂閱者,觸發對應的監聽回呼。

假如寫過C#winform自訂控制項的,我想更能理解之後的邏輯和實作原理

C#中當控制項的某個屬性發生了變化,就刷新視圖

priveate int  a ;
public  int A
{
   get { return a; }
   set { if(a!=value){a = value; Invalidate(); } }
}

# 当a的值发生变化, 就重绘视图
登入後複製

再來看看Object.defineProperty(obj, prop, descriptor) 方法

位址:https://developer. mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty()方法會直接在一個物件上定義一個新屬性,或修改一個物件的現有屬性,並傳回這個物件。

  • obj需要被操作的目標物件

  • #prop目標物件需要定義或修改的屬性的名稱。

  • descriptor將被定義或修改的屬性的描述符

<strong>descriptor</strong>

  • configurable當且僅當該屬性的configurabletrue時,此屬性描述符才能夠被改變,同時屬性也能從對應的物件上被刪除。預設為false

  • enumerable當且僅當該屬性的enumerabletrue時,該屬性才能夠出現在對象的枚舉屬性中。預設為false。資料描述符同時具有以下可選鍵值:

  • value該屬性對應的值。可以是任何有效的JavaScript值(數值,對象,函數等)。預設為undefined

  • writable當且僅當該屬性的writabletrue時,該屬性才能被賦值運算符改變。預設為false。存取描述符同時具有以下可選鍵值:

  • get一個給屬性提供getter的方法,如果沒有 getter則為undefined。此方法傳回值被用作屬性值。預設為undefined

  • set一個給屬性提供setter的方法,如果沒有setter則為undefined。此方法將接受唯一參數,並將該參數的新值指派給該屬性。預設為undefined

先來實作一個簡單資料劫持

var A = {};
var a = "";
Object.defineProperty(A, "a", {
  set: function (value) {
    a = value;
  },
  get: function () {
    return "My name is " + a;
  },
});

A.a = "chuchur";
console.log(A.a); // My name is chuchur
登入後複製

不光是這麼簡單,來看下vue的程式碼

<div id="app">
  <input type="text" v-model="word" />
  <p>{{word}}</p>
  <button v-on:click="sayHi">change model</button>
</div>
<script>
  var vm = new Vue({
    el: "#app",
    data: {
      word: "Hello World!",
    },
    methods: {
      sayHi: function () {
        this.word = "Hi, everybody!";
      },
    },
  });
</script>
登入後複製

已經實現的簡單的資料劫持,那麼有多個屬性,就要實現一個資料監聽器Observer,能夠對資料物件的所有屬性進行監聽,還需要一個訂閱器Dep來收集這些屬性的變動來通知訂閱者

元素節點的v-model,v-on:click,就需要實作一個指令解析器Compile ,對每個元素節點的指令進行掃描和解析,根據指令模板替換數據,以及綁定相應的更新函數

最后实现一个订阅者Watcher,作为连接ObserverCompile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

大概的流程图如下:

解析vue中observer資料雙向綁定原理(程式碼分享)

实现Observer

将需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上settergetter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

// observe
function observe(data) {
  if (data && typeof data === "object") {
    // 取出所有属性遍历
    Object.keys(data).forEach(function (key) {
      defineReactive(data, key, data[key]);
    });
  }
  return;
}

function defineReactive(data, key, val) {
  observe(val); // 监听子属性
  Object.defineProperty(data, key, {
    enumerable: true, // 可枚举
    configurable: false, // 不能再define
    get: function () {
      return val;
    },
    set: function (value) {
      console.log("监听到值变化了: ", val, "==>", value);
      val = value;
    },
  });
}
var A = {
  fristName: "chuchur",
  age: 29,
};
observe(A);

A.fristName = "nana"; //监听到值变化了:  chuchur ==> nana
A.age = 30; //监听到值变化了:  29 ==> 30
登入後複製

这样就实现了多个属性的监听,接下来就是实现订阅器Dep,当这些属性变化的时候,触发通知notify,告诉执行订阅者执行更新函数

//Dep
function Dep() {
  this.subs = [];
}
Dep.prototype = {
  addSub: function (sub) {
    this.subs.push(sub);
  },
  notify: function () {
    this.subs.forEach(function (sub) {
      sub.update();
    });
  },
};
登入後複製

把订阅器植入到监听器里

function defineReactive(data, key, val) {

  var dep = new Dep()
  observe(val); //监听子属性
  Object.defineProperty(data, key, {
    set: function(value) {
      dep.notify() //发出通知, 我被改变了
    }
  });

}
登入後複製

至此,简陋的监听器就实现完成了,接下来继续完成Watcher

推荐学习:vue.js教程

以上是解析vue中observer資料雙向綁定原理(程式碼分享)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
vue
來源:chuchur.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!