首頁  >  文章  >  web前端  >  一文了解vue中watcher資料雙向綁定原則(附程式碼)

一文了解vue中watcher資料雙向綁定原則(附程式碼)

奋力向前
奋力向前轉載
2021-08-23 10:09:272206瀏覽

之前的文章《解析vue中observer資料雙向綁定原理(程式碼分享)》中,給大家了解了vue中observer資料雙向綁定原理。以下這篇文章給大家了解vue中watcher資料雙向綁定原理,一定的參考價值,有需要的朋友可以參考一下。

一文了解vue中watcher資料雙向綁定原則(附程式碼)

vue資料雙向綁定原理,和簡單的實作,本文將實作mvvm watcher

一文了解vue中watcher資料雙向綁定原則(附程式碼)

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

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

3)vue資料雙向綁定原理-解析器Complie

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

#上面的步驟已經實現了監聽器,和訂閱器,當屬性發生改變,發出通知,那麼這個通知是通知誰呢,肯定是訂閱者watcher.Watcher訂閱者作為ObserverCompile之間通信的橋樑,主要做的事情是:

1、在自身實例化時往屬性訂閱器(dep)裡面加入自己

2、自身必須有一個update()方法

3、待屬性變動dep.notice()通知時,能呼叫自身的update()方法,並觸發Compile中綁定的回調,則釋放自己。

// Watcher
function Watcher(vm, exp, cb) {
  this.cb = cb;
  this.$vm = vm;
  this.exp = exp;
  // 此处为了触发属性的getter,从而在dep添加自己,结合Observer更易理解
  this.value = this.get(); // 将自己添加到订阅器的操作
}
Watcher.prototype = {
  update: function () {
    this.run(); // 属性值变化收到通知
  },
  run: function () {
    var value = this.get(); // 取到最新值
    var oldVal = this.value;
    if (value !== oldVal) {
      this.value = value;
      this.cb.call(this.$vm, value, oldVal); // 执行Compile中绑定的回调,更新视图
    }
  },
  get: function () {
    Dep.target = this; // 将当前订阅者指向自己, 缓存
    var value = this.$vm[this.exp]; // 强制触发监听的getter,添加自己到属性订阅器中
    Dep.target = null; // 添加完毕,重置释放
    return value;
  },
};

訂閱者要快取自己,並且告訴監聽器,要把我加到訂閱器裡面去。所以也要改造下監聽器

function defineReactive(data, key, val) {
  var dep = new Dep()
  observe(val); // 监听子属性
  Object.defineProperty(data, key, {
    ....
    get: function() {
      // 由于需要在闭包内添加watcher,所以可以在Dep定义一个全局target属性,暂存watcher, 添加完移除
      Dep.target && dep.addDep(Dep.target);
      return val;
    },
    ....
  });

}

實例化Watcher的時候,呼叫get()方法,透過Dep.target=watcherInstance標記訂閱者是目前watcher實例,強行觸發屬性定義的getter方法,getter方法執行的時候,就會在屬性的訂閱器 dep新增目前watcher實例,以便在屬性值有變化的時候watcherInstance就能收到更新通知。

實作MVVM

到這兒先將監聽器Observer和監聽者Watcher連起來,先模擬一些數據,實作簡單的資料綁定

<div id="name"></div>
<script>
  function Vue(data, el, exp) {
    this.data = data;
    observe(data);
    el.innerHTML = this.data[exp]; // 初始化模板数据的值
    new Watcher(this, exp, function (value) {
      el.innerHTML = value;
    });
    return this;
  }
  var ele = document.querySelector("#name");
  var vue = new Vue(
    {
      name: "hello world",
    },
    ele,
    "name"
  );
  setInterval(function () {
    vue.data.name = "chuchur " + new Date() * 1;
  }, 1000);
</script>

這可以看到div的和內容初始為hello world,每隔一秒之後變換為chuchur 加上時間戳,雖然是實現了,但是與想像的還差很多。是vue.name不是vue.data.name,所以這裡需要為Vue實例新增一個屬性代理的方法,使存取vm的屬性代理為存取vm.data的屬性,改造後的程式碼如下:

function Vue(options) {

  this.$options = options || {};
  this.data = this.$options.data;
  // 属性代理,实现 vm.xxx -> vm.data.xxx
  var self = this;
  Object.keys(this.data).forEach(function(key) {

    self.proxy(key); // 绑定代理属性

  });
  observe(this.data, this);
  el.innerHTML = this.data[exp]; // 初始化模板数据的值
  new Watcher(this, exp, function(value) {

    el.innerHTML = value;

  });
  return this;

}

Vue.prototype = {

  proxy: function(key) {
    var self = this;
    Object.defineProperty(this, key, {
      enumerable: false,
      configurable: true,
      get: function proxyGetter() {
        return self.data[key];
      },
      set: function proxySetter(newVal) {
        self.data[key] = newVal;
      }
    });
  }

}

然後就可以透過vue.name,直接改版模板的數據了,下一步就要實作解析器Complie 

[完]

#推薦學習:vue.js教學

###############################################

以上是一文了解vue中watcher資料雙向綁定原則(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:chuchur.com。如有侵權,請聯絡admin@php.cn刪除