Skip to content

Vue 3 中的 Object.assign 与响应式丢失问题

Vue 3 的响应式原理

Vue 3 使用 Proxy 来创建响应式对象:

javascript
// Vue 3 使用 Proxy 来创建响应式对象
const formState = reactive({
  name: '',
  age: 0
});

// 这时 formState 的现有属性是响应式的

Object.assign 的问题

javascript
// 错误示例
Object.assign(formState, {
  name: 'John',
  newProp: 'value' // 新属性不会被转换为响应式
});

// 正确示例
formState.name = 'John'; // 已存在的属性会保持响应式

为什么会丢失响应式

  • Object.assign 是直接复制属性,绕过了 Vue 的响应式系统
  • 新添加的属性不会自动变成响应式
  • 只有在创建 reactive 对象时声明的属性才会被正确追踪

正确的更新方式

javascript
// 方式1:逐个赋值
Object.keys(newData).forEach(key => {
  if (formState.hasOwnProperty(key)) {
    formState[key] = newData[key];
  }
});

// 方式2:使用解构赋值
const { name, age } = newData;
formState.name = name;
formState.age = age;

// 方式3:如果确实需要添加新属性,使用 ref 或 reactive
const newFormState = reactive({
  ...formState,
  newProp: 'value'
});

实际应用示例

javascript
// 在组件中的正确使用方式
const formState = reactive({
  name: '',
  age: 0,
  // 预先定义所有可能的属性
  additionalInfo: null
});

const updateFormState = (newData) => {
  // 安全地更新现有属性
  Object.keys(formState).forEach(key => {
    if (newData[key] !== undefined) {
      formState[key] = newData[key];
    }
  });
};

最佳实践建议

  1. 预先声明所有可能的属性
  2. 使用逐个赋值的方式更新数据
  3. 如果需要添加新属性,考虑重新创建响应式对象

这样可以确保数据的响应式特性被正确维护。