1.封装的数组方法有哪些,其如何实现页面更新
在Vue中,对响应式处理利用的是Object.defineProperty对数据进行拦截,而这个方法并不能监听到数组内部变化,数组长度变化,数组的截取变化等,所以需要对这些操作进行hack(入侵),让Vue能监听到其中的变化。
1.vue封装的数组方法有:
2.如何实现页面更新:
该代码是对以上数组方法的封装:
const arrayProto = Array.prototype;
// 实现 arrayMethods.__proto__ === Array.prototype
export const arrayMethods = Object.create(arrayProto);
// 需要进行功能拓展的方法
const methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse"
];
/**
* Intercept mutating methods and emit events
*/
methodsToPatch.forEach(function(method) {
// 缓存原生数组方法
const original = arrayProto[method];
def(arrayMethods, method, function mutator(...args) {
// 执行并缓存原生数组功能
const result = original.apply(this, args);
// 响应式处理
const ob = this.__ob__;
let inserted;
switch (method) {
// push、unshift会新增索引,所以要手动observer
case "push":
case "unshift":
inserted = args;
break;
// splice方法,如果传入了第三个参数,也会有索引加入,也要手动observer。
case "splice":
inserted = args.slice(2);
break;
}
//
if (inserted) ob.observeArray(inserted);// 获取插入的值,并设置响应式监听
// notify change
ob.dep.notify();// 通知依赖更新
// 返回原生数组方法的执行结果
return result;
});
});
简单来说就是,重写了数组中的那些原生方法,首先获取到这个数组的__ob__,也就是它的Observer对象,如果有新的值,就调用observeArray继续对新的值观察变化(也就是通过target__proto__ == arrayMethods来改变了数组实例的型),然后手动调用notify,通知渲染watcher,执行update。
2.总结:
1.封装数组的原因:
Vue中,使用Object.defineProperty实现响应式数据的拦截,不能监听到数组内部、长度、截取的变化,因此需要对这些操作进行hack,让Vue监听其变化,并对被侦听到的数组变更方法进行包裹,触发视图更新。
2.封装的数组方法:
push()、pop() 、shift() 、unshift() 、splice()、 sort()、 reverse()
3.该封装的数组方法如何实现页面更新:
重写了数组中的原生方法。具体过程如下:
1.获取到该数组的监听对象,如果有新的值,调用监听数组继续对新值进行监听observer(target_proto_=arrayMethods,来改变数组实例的型)
2.手动调用notify(通知依赖dep更新的方法),通知渲染watcher
3.执行update,即:进行页面数据的更新。
Observer: 这里的主要工作是递归地监听对象上的所有属性,在属性值改变的时候,触发相应的Watcher。
Watcher: 观察者,当监听的数据值修改时,执行响应的回调函数,在Vue里更新模板内容。
Dep: 链接Observer和Watcher的桥梁,每一个Observer对应一个Dep,它内部维护一个数组,保存与该Observer相关的Watcher
一句话说:
observer 监听数组对象的属性,当值发生改变时就会触发Watcher来执行响应的回调函数,更新页面。