MST

星途 面试题库

面试题:Vue 3中Proxy如何实现数组的响应式改进

在Vue 3中,Proxy相较于Vue 2的Object.defineProperty,对数组响应式做了哪些改进?请简要阐述其原理和实现方式。
44.7万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

改进点

  1. 直接操作数组长度:在Vue 2中,通过Object.defineProperty对数组的length属性进行响应式处理存在局限性,直接修改数组的length属性不会触发视图更新。而Vue 3使用Proxy可以直接对数组length的变化做出响应,当修改length时能自动更新视图。
  2. 新增数组方法的响应式:Vue 2中对一些数组的变异方法(如pushpopshiftunshiftsplicesortreverse)进行了重写来实现响应式,但对于非变异方法(如filtermapforEach等)返回的新数组不是响应式的。Vue 3的Proxy可以对所有数组操作方法都进行拦截,无论是变异方法还是非变异方法,使得新生成的数组也具有响应式。

原理

Proxy是ES6提供的用于创建对象代理的构造函数。它可以对目标对象的各种操作(如读取、赋值、枚举、函数调用等)进行拦截和自定义操作。在Vue 3中,利用Proxy的这一特性,对数组的所有操作进行拦截。当数组发生变化时,Proxy能够捕获到这些变化,然后通知依赖该数组的组件进行更新。

实现方式

在Vue 3中,reactive函数内部会判断传入的值是否为数组,如果是数组则通过new Proxy(target, handler)创建一个代理对象。其中handler定义了各种拦截操作,例如:

const arrayProto = Array.prototype
const mutableHandlers = {
  get(target, key, receiver) {
    const res = Reflect.get(target, key, receiver)
    // 收集依赖
    track(target, TrackOpTypes.GET, key)
    return res
  },
  set(target, key, value, receiver) {
    const oldValue = target[key]
    const result = Reflect.set(target, key, value, receiver)
    if (oldValue !== value) {
      // 触发更新
      trigger(target, TriggerOpTypes.SET, key, value, oldValue)
    }
    return result
  }
}
function reactive(target) {
  return new Proxy(target, mutableHandlers)
}

对于数组的特定操作,如length属性的修改、数组方法的调用等,Proxyhandler中都有相应的拦截逻辑,从而实现对数组的全面响应式处理。