面试题:Vue 中封装的数组方法有哪些?它们如何实现视图更新?

在 Vue 中,为了实现对数组的响应式更新,Vue 封装了一些原生的数组方法。这些方法会触发视图更新,从而确保数据变化能够反映到 UI 上。以下是 Vue 封装的数组方法及其实现原理:


1. Vue 封装的数组方法

Vue 对以下数组方法进行了封装:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

这些方法在 Vue 中被重写,使得调用它们时能够触发视图更新。


2. 如何实现视图更新

Vue 的响应式系统基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)。对于数组,Vue 通过以下方式实现视图更新:

Vue 2 的实现

  • 拦截数组方法
    • Vue 2 重写了数组的原型方法,使得调用这些方法时能够触发依赖更新。
    • 具体实现是通过创建一个新的原型对象,继承自 Array.prototype,并重写上述方法。
  • 依赖收集
    • 当访问数组时,Vue 会收集依赖(Watcher)。
    • 当调用封装的数组方法时,Vue 会通知依赖更新视图。
// Vue 2 的数组方法封装示例
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);

['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
  const original = arrayProto[method];
  Object.defineProperty(arrayMethods, method, {
    value: function mutator(...args) {
      const result = original.apply(this, args);
      const ob = this.__ob__; // 获取 Observer 实例
      ob.dep.notify(); // 通知依赖更新
      return result;
    },
    enumerable: false,
    writable: true,
    configurable: true,
  });
});

Vue 3 的实现

  • 基于 Proxy
    • Vue 3 使用 Proxy 实现响应式系统,能够直接监听数组的变化。
    • Proxy 可以拦截数组的所有操作,包括索引赋值、length 修改等。
  • 自动触发更新
    • 当数组发生变化时,Proxy 会自动触发视图更新。
// Vue 3 的数组响应式示例
const reactiveArray = new Proxy([], {
  set(target, key, value, receiver) {
    const result = Reflect.set(target, key, value, receiver);
    trigger(target, 'set', key); // 触发更新
    return result;
  },
});

3. 注意事项

  • 直接修改数组索引或长度
    • 在 Vue 2 中,直接通过索引修改数组(如 arr[0] = newValue)或修改 length 不会触发视图更新。
    • 在 Vue 3 中,由于使用了 Proxy,这些操作可以触发视图更新。
  • 解决方法
    • 在 Vue 2 中,可以使用 Vue.set 或 this.$set 来修改数组元素,确保触发视图更新。
    • 在 Vue 3 中,直接修改即可。
// Vue 2 中触发视图更新
Vue.set(arr, index, newValue);

// Vue 3 中直接修改
arr[index] = newValue;

4. 示例

Vue 2 示例

export default {
  data() {
    return {
      items: [1, 2, 3],
    };
  },
  methods: {
    addItem() {
      this.items.push(4); // 触发视图更新
    },
    updateItem() {
      Vue.set(this.items, 0, 10); // 触发视图更新
    },
  },
};

Vue 3 示例

import { reactive } from 'vue';

export default {
  setup() {
    const items = reactive([1, 2, 3]);

    function addItem() {
      items.push(4); // 触发视图更新
    }

    function updateItem() {
      items[0] = 10; // 触发视图更新
    }

    return {
      items,
      addItem,
      updateItem,
    };
  },
};

总结

  • Vue 2
    • 封装了数组方法(pushpop 等),通过重写原型方法实现视图更新。
    • 直接修改数组索引或长度不会触发更新,需使用 Vue.set
  • Vue 3
    • 使用 Proxy 实现响应式,能够监听所有数组操作。
    • 直接修改数组索引或长度即可触发更新。

通过封装数组方法,Vue 确保了数组操作的响应式特性,使得数据变化能够自动反映到视图上。

THE END
点赞13 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容