失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > vue 监听表格里的数据变化_vue中监听object数据变化的基本原理

vue 监听表格里的数据变化_vue中监听object数据变化的基本原理

时间:2019-04-21 02:37:47

相关推荐

vue 监听表格里的数据变化_vue中监听object数据变化的基本原理

# 简略版+自己的注释//判断一个变量是否是对象

functionisObject(obj){

returnobj.constructor===Object

}

classObserver{

constructor(value){

this.value=value;

if(!arr.isArray(value)){

this.walk(value);

}

}

walk(obj){

constkeys=Object.keys(obj);

//循环将obj中的每一个属性转换成getter/setter进行变化追踪

for(leti=0;i

defineReactive(obj,keys[i],obj[keys[i]]);

}

}

}

functiondefineReactive(data,key,val){

if(isObject(val)){

newObserver(val);//进行递归调用

}

letdep=newDep();

Object.defineProperty(data,key,{

configurable:true,

enumerable:true,

get:function(){

dep.depend();

returnval;

},

set:function(newVal){

if(val===newVal)return

//如果赋值的新值也是一个对象也需要进行侦测

if(isObject(newVal)){

newObserver(val);//进行递归调用

}

val=newVal;

dep.notify();//通知所有的订阅者,数据要被修改了,做出相应的行为(也就是执行对应的回调函数)

}

})

}

classDep{

constructor(){

this.subs=[]//这个里面存放的是Watch实例对象

}

addSub(sub){

this.subs.push(sub);//在这个地方收集订阅者

}

removeSub(sub){

remove(this.subs,sub);

}

depend(){

if(window.target){

this.addSub(window.target);//在这个地方触发depend方法,进行收集订阅者

}

}

notify(){

constsubs=this.subs.slice();

for(leti=0;i

subs[i].update();//在这个地方执行回调函数

}

}

}

functionremove(arr,item){

if(arr.length){

constindex=arr[item];

if(index>-1){

returnarr.splice(index,1);

}

}

}

classWatcher{

constructor(vm,expOrFn,cb){

this.vm=vm;

this.getter=parsePath(expOrFn);

this.cb=cb;

this.value=this.get();//获取expOrFn中的值在这个内部同时会触发getter,从而在dep中添加自己

}

get(){

window.target=this;//将watch实例对象赋值给全局的target变量上

letvalue=this.getter.call(this.vm,this.vm);//该代码的作用很关键

//如果expOrFn直接是一个表达式不是一个函数eg:'name','age'假设只有一个属性不是这种的'name.a.b'

//我们就可以直接下面这样写,只是为了测试理解,vue.js源码处理更加全面

//letvalue=this.vm[this.expOrFn]//vm就是要监听的数据,当然expOrFn要在constructor中挂在到this身上

window.target=undefined;

returnvalue;

}

update(){

constoldValue=this.value;

this.value=this.get();

this.cb.call(this.vm,this.value,oldValue);

}

}

//该方法的作用是将'name.a.b'这种表达式的值取出来

//也就是通过该方法返回的是obj['name']['a']['b]的值

functionparsePath(path){

constbailRE=/[^\w.$]/;

constsegments=path.split('.')

//闭包

returnfunction(obj){

for(leti=0;i

if(!obj)return

obj=obj[segments[i]]//取出属性的值所以这个地方会执行getter

}

returnobj;//返回属性的值

}

}

letbtns=document.getElementsByTagName('button');

//定义数据

letperson={};

//定义响应式数据的属性

defineReactive(person,'name','乔峰')

//监听数据

letw=newWatcher(person,'name',function(newVal,oldVal){

console.log('数据发生变化了')

console.log(newVal,oldVal);

})

//1.取值操作

person.name

//2.改变数据

btns[0].onclick=function(){

person.name='小龙女';

}

# 总结

1.在实例化一个Watcher对象时,其get方法中会触发defineReactive中的getter访问器,在其getter访问器中会执行dep.depend()方法,dep.depend()方法会调用this.subs.push(sub)方法,从而收集依赖,也就是在subs 中存放的是当前的Watcher实例对象

2.Watch实例对象自身必须有一个update方法

3.当数据发生变化时,会触发defineReactive中的setter访问器,在其setter访问器中会调用subs[i].update()方法,其中的每一个subs[i]就是watch实例对象,从而执行了update方法,在update方法中执行了this.cb.call(this.vm, this.value, oldValue)回调函数

3.Observer 类是用来将传递进来的数据遍历转换成响应式数据,也就是转换成getter/setter的形式进行侦测

4.在使用的时候,我们首先需要调用defineReactive方法,来创建一个响应式数据,然后再调用Watcher方法来监听这个响应式数据的变化,然后就能做到数据驱动,或者叫响应式数据

______如有不对,请指正_______

如果觉得《vue 监听表格里的数据变化_vue中监听object数据变化的基本原理》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。