首页 > 编程知识 正文

vue实战,深入浅出jquery

时间:2023-05-04 07:04:57 阅读:174002 作者:3595

1 什么是变化侦测在运行过程中,APP应用程序的状态会不断变化。 页面必须重复渲染页面。 你如何判断其中的状态发生了什么变化?

变化检测就是为了解决这个问题,转换检测也是响应型系统的核心,没有它就不会进行重新渲染。

2 如何追踪变化js有两种跟踪变化的方法。 Object.defineProperty和Proxy。 Vue.js目前正在使用Object.defineProperty,因为ES6在浏览器中的支持程度不够高。

Object.defineProperty是js提供的方法,通过该方法可以定义对象的新属性或修改现有属性来返回对象。 读取数据时,将自动调用其中的get方法,并在设置时调用set方法。

functiondefinereactive(data,key,val ) object.defineproperty ) data,key,{ enumerable:true,get 3360 function } } defineReactive用于封装Object.defineProperty,封装后只需传递data、key和val即可。

从data key读取数据时,将调用get函数;设置数据时,将调用set函数。

在33558www.Sina.com/Getter上收集依赖关系,并在setter上触发依赖关系

3如何收集依赖封装用于管理依赖的Dep类,可以进行依赖的收集、删除或对依赖的通知。

exportdefaultclassdep { constructor () } { this.subs=[ ]; }收集}addsub(sub )//this.subs.push ) sub ); }removesub(sub )//remove (this.subs,sub ) } depend ) ) if ) window.target ) this.addsub ) window.target ) ttttif for(letI=0,l=subs.length; il; I ) { subs[i].update (; }functionremove(arr,item ) if ) arr.length ) constindex=arr.indexof ) item ); if(index-1 )返回arr.splice (index,1 ); } }在改造中defineReaactive

functiondefinereactive(data,key,val ) ) { let dep=new Dep ); //object.defineproperty(data,key,{ enumerable:true,get:function () { dep.depend ) }//returnval ) dep.notify (; //新} 4 依赖收集在哪里状态变化不是最终结果,而是告知使用该状态的场所发生了变化。

在进入这种状态的时候,我们需要收集的,也就是依赖。

但是,使用这个数据的地方很多,而且类型还不一样,可能是模板,也可能是用户编写的watch,所以需要抽象出能够集中处理这些情况的类。 在依赖收集阶段,只有这个封装类的实例会进入,通知也会随之通知。 给它取了个很棒的名字: Watcher。 也就是说,是依存。

5 依赖是谁Watcher是中介,在数据发生变化时通知其他地方。

经典用法:

VM.$watch('name ',function ) ) newval

, oldVal) { // something});

把window.target赋一个this,再读一下值,触发getter,就可以将this主动添加到依赖数组的dep中。

之后,每当name的值发生变化,就会触发update方法,在其中执行参数中的回调函数。

(该部分来源https://blog.csdn.net/qq_16858683/article/details/101371154)

export default class Watcher { constructor(vm, expOrFn, cb) { // vm为vue实例 // expOrFn为表达式或函数(这个函数可能访问了多个数据,就会创建多个依赖),在上面的例子里,expOrFn为"name" // cb为回调函数,callback的缩写 this.vm = vm; // 解析expOfFn的路径,读取它的值(parsePath函数是一个闭包,返回的是一个函数,该函数参数应该传这个值所在对象,其实就是vm) // 所以这里getter只是一个函数 this.getter = parsePath(expOfFn); this.cb = cb; // 每实例化一个Watcher,都自动触发get(),触发收集依赖的逻辑 this.value = this.get(); } get() { window.target = this; // 读取expOrFn的值,从而触发了"name"的getter,从而触发了收集依赖:dep.depend(); // depend() { // if (window.target) this.addSubs(window.target); // } // 而depend()中是将window.target存入依赖,此时windo.target指向了Watcher的this!,正好把这个Watcher存入依赖,妙啊 let value = this.getter.call(this.vm, this.vm); // 用完window.target就置为undefined,备胎... window.target = undefined; return value; } // "name"数据改变时,触发它自己的setter,然后遍历依赖。触发了该watcher的update方法。 // 该方法调用回调函数 update() { // 此时watcher中的value是老的值 const oldValue = this.value; // 通过get()获取"name"最新的值,get中会判断这个watcher是否被加入到依赖中,防止重复添加依赖 this.value = this.get(); // callback中的this指向vm,然后传入newVal,oldVal,执行callback this.cb.call(this.vm, this.value, oldValue); }}

到现在,已经实现了变化侦测的功能,但只能侦测数据中的某一个属性。

7 Observer类

为了侦测到数据的所有属性,包括子属性,封装一个Observer类。这个类的作用是将一个数据里的所有属性都转换成getter/setter的形式,然后追踪它们的变化。

(该部分来源https://blog.csdn.net/qq_16858683/article/details/101371154)

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]]); } }}function defineReactive(data, key, val) { // 如果子属性还是个对象,则递归为这个对象的子属性添加侦测 if (type val === "object") new Observer; let dep = new Dep(); Object.defineProperty (data, key, { enumerable: true, configurable: true, get: function () { // 在getter中收集依赖 dep.depend(); return val; }, set: function (newVal) { if (val === newVal) return; val = newVal; // 在setter中通知依赖 dep.notify(); } })} 8 总结

Data通过Observer转换成getter/setter的形式来追踪变化。

当外界通过Watcher读取数据时,会触发getter将Watcher添加到依赖中。

当数据发生了变化,会触发setter,从而向Dep中的依赖(Watcher)发送通知。

Watcher接收到通知后,会向外界发送通知,变化通知到外界后可能会触发视图更新,也可能触发用户的某个回调函数。

注:

Vue.js通过Object.defineProperty来将对象的key转换成getter/setter的形式来追踪变化,但getter/setter只能追踪一个数据是否被修改,无法追踪新增属性和删除属性

但Vue提供了两个API解决这个问题

vm.$setvm.$delete

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。