Vue插件開發一系列api Vue.util.defineReactive 手寫實現

寫在開頭

本文探索Vue插件開發一系列api ,很重要的一個就是:Vue.util.defineReactive,它就是Vue監聽current變量重要執行者

console.log(Vue.util);

執行結果:

Vue.util.defineReactive

很重要的一個就是:Vue.util.defineReactive,它就是Vue監聽current變量重要執行者

不妨從源碼來學習:

/**
   * Define a reactive property on an Object.
   */
  //Vue的data監聽,也是通過這個方法
  function defineReactive$$1 (
    obj,
    key,
    val,
    customSetter,
    shallow
  ) {
	//依賴收集者
    var dep = new Dep();

    var property = Object.getOwnPropertyDescriptor(obj, key);
    if (property && property.configurable === false) {
      return
    }

    // cater for pre-defined getter/setters
    var getter = property && property.get;
    var setter = property && property.set;
    if ((!getter || setter) && arguments.length === 2) {
      val = obj[key];
    }

    var childOb = !shallow && observe(val);
	//雙向綁定
    Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get: function reactiveGetter () {
        var value = getter ? getter.call(obj) : val;
        if (Dep.target) {
		  //進行依賴收集
          dep.depend();
		  /*採用依賴收集的原因:*/
          //1.data裏面的數據並不是所有地方都要用到
          //2.如果我們直接更新整個視圖,會造成資源浪費
		  //3.將依賴於某個變量的組件收集起來
          if (childOb) {
            childOb.dep.depend();
            if (Array.isArray(value)) {
              dependArray(value);
            }
          }
        }
        return value
      },
      set: function reactiveSetter (newVal) {
        var value = getter ? getter.call(obj) : val;
        /* eslint-disable no-self-compare */
        if (newVal === value || (newVal !== newVal && value !== value)) {
          return
        }
        /* eslint-enable no-self-compare */
        if (customSetter) {
          customSetter();
        }
        // #7981: for accessor properties without setter
        if (getter && !setter) { return }
        if (setter) {
          setter.call(obj, newVal);
        } else {
          val = newVal;
        }
        childOb = !shallow && observe(newVal);
        //觸發依賴的組件產生更新
		dep.notify();
      }
    });
  }

雙向綁定

上述關於響應式 雙向綁定,強烈推薦之前寫過的一篇文章:

推薦閱讀:Vue 技術棧 手寫響應式原理 到 探索設計模式

手寫實現defineReactive

我們可以通過defineReactive來實現Vue監聽current的監視者,監聽某個第三方的變量

手寫:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

//Vue插件開發一系列api
//console.log(Vue.util.defineReactive);
//test是屬於window的對象
var test={
	testa:'計時開始'
}
//設置定時器
setTimeout(function(){
	test.testa='計時結束'
},2000)
function a(){
  console.log(6);
}
a.install=function(vue){
	//console.log(vue);
	//監聽testa
	Vue.util.defineReactive(test,'testa');
	//全局混入vue實例
	vue.mixin({
		data(){
			return {
				c:'歡迎訪問超逸の博客'
			}
		},
		methods:{
		},
		beforeCreate:function(){
			this.test=test;
		},
		//全局生命週期注入
		created:function(){
			//console.log(this)
		}
		
	});
}
Vue.use(a);
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

然後我們在HelloWorld組件進行渲染,查看頁面

執行結果:

疑問:爲什麼要寫在beforeCreate裏面?

解決:因爲create階段組件已經生成了,this實例已經創建了,而beforeCreate纔剛開始。這樣HelloWorld組件可以this調用來獲取testa的值

學如逆水行舟,不進則退
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章