Vue——封装的数组方法有哪些,其如何实现页面更新

543 阅读2分钟

1.封装的数组方法有哪些,其如何实现页面更新

在Vue中,对响应式处理利用的是Object.defineProperty对数据进行拦截,而这个方法并不能监听到数组内部变化,数组长度变化,数组的截取变化等,所以需要对这些操作进行hack(入侵),让Vue能监听到其中的变化。

1.vue封装的数组方法有:

image.png

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: 链接ObserverWatcher的桥梁,每一个Observer对应一个Dep,它内部维护一个数组,保存与该Observer相关的Watcher

一句话说:

observer 监听数组对象的属性,当值发生改变时就会触发Watcher来执行响应的回调函数,更新页面。