Vue 中给对象添加新属性为何界面不刷新?

探讨在 Vue.js 中,当直接向对象添加新属性时为何界面不会刷新,并提供解决方案。

Vue 中等 响应式 响应式数据 数据劫持

原因: 这是由于 Vue 2 的响应式机制基于 Object.defineProperty 实现数据劫持。 该机制在初始化实例时遍历 data 对象的已有属性,将其转化为 getter/setter 以便追踪属性变化。但当直接在已初始化的对象上添加新属性时,新增属性没有经过此过程,Vue 无法自动检测变化并触发视图更新。

以下是主要解决方案(基于官方推荐):

  1. 使用 Vue.set() 或 实例方法 this.$set()
    语法:Vue.set(target, key, value)this.$set(target, key, value)
    Example:
    // 对象添加新属性
    this.$set(this.obj, 'newProperty', value);
    // 数组添加新元素(索引位置)
    this.$set(this.array, index, value);
    
  2. 使用 Object.assign() 创建新对象
    通过创建新对象并替换原引用,确保 Vue 能检测变化。
    Example:
    this.obj = Object.assign({}, this.obj, { 
      newProperty: value 
    });
    
  3. $forceUpdate()(不推荐)
    强制 Vue 实例重新渲染界面,但它绕过响应式机制,建议只在非响应式方案无效时临时使用。
    Example:
    this.newProperty = value;
    this.$forceUpdate();
    

重要注意事项:

  • 在 Vue 3 中使用 composition API 无此问题,但 Vue 2 需依赖以上方法。
  • 参考上述方案时优先用 $set