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的值

学如逆水行舟,不进则退
发布了581 篇原创文章 · 获赞 1694 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/weixin_42429718/article/details/104815942
今日推荐