vue双向绑定原理简化版Obejct---(一)

177 阅读1分钟

1.何为响应式?

当一个数据发生改变,视图会随之刷新,并匹配最新的值。就叫响应式。

2.如何实现响应式?

初步构想,一个数据的改变应该会有监听函数,去监听其数据改变,并有办法去通知其视图的更改

3.实现监听--首先请出Object.defineProperty函数,先看个demo

 var obj = {
   name: '11',
   sex: '男'
  }
 let keys = Object.keys(obj)
 for(let i in keys){
   let value = obj[keys[i]]
   Object.defineProperty(obj, keys[i], {
     get(){
       console.log('get')
       return value
     },
     set(){
       console.log('set')
     }
   })
 }
 console.log(obj.name) //打印出get 11 
 obj.name = '张三' //打印出set

从这个示例中可以看出通过Object.defineProperty函数我们可以实现对object的get和set函数的重写。那么下一步我们需要对其进行监听。

4.实现依赖当前数据的收集

1.首先我们先实现一个简单的对依赖收集的类

  class Dep {
      constructor(){
          this.subs = []
      },
      //增加
      depend(){
          if(window.target){
              this.subs.push(window.target) //这个window.target(也就是后面的watcher)我们暂时不急着解释
          }
      },
      //通知
      notify(){
      	const subs = this.subs.slice()
        for(let i = 0, l=sub.length; i < l; i++){
        	subs[i].notify()
       	}
     }
     //还有一些增删的方法自行去看源码
  }

2. 开始进行依赖的收集

	function defineReactive(data, key, val){
		let dep = new Dep()
       	Object.defineProperty(data, key, {
        		get: function(){
            		dep.depend()
              		return val
           		},
                set: function(newVal){
                	if(val === newVal) return
                    val = newVal
                    dep.notify();
      	})
	}

3.因为上面我们说的是一个属性的监听,而我们希望监听到对象的所有属性,所以我们再封装一个Observer类去作为中间层接受对象(也就是vm.$options.data)处理

export class Observer{
     constructor(value){
    	this.value = value;
        if(!Array.isArray(value)){
        	this.walk(value)
           }
      }
      walk(obj){
      	const keys = Object.keys(obj)
        for(let i = 0; i <= keys.length; i++){
        	defineReactive(obj, keys[i], obj[keys[i]])
         }
      }
}

5.总结(我们大致的流程图)

6.夺命三问

1.所以我们为什么监听不到对象属性的新增?

因为对象增加属性(比如this.obj.age = 22),并没有对其age属性进行get,set的监听和收集,所以自然不会触发视图更新

2.已知我们vue.$options.data是对象。那里面的数组是如何触发更新的?

等下一篇文章详解

3.第三问捏造不出来了