
在 Vue 2 中,直接修改数组中对象的属性(如 item.price = ...)无法触发视图更新;必须通过 this.$set 显式声明响应式变更,否则模板不会同步——即使 console.log 显示值已改变。
在 vue 2 中,直接修改数组中对象的属性(如 `item.price = ...`)无法触发视图更新;必须通过 `this.$set` 显式声明响应式变更,否则模板不会同步——即使 `console.log` 显示值已改变。
Vue 2 的响应式系统对数组的变更检测存在限制:它无法探测通过索引直接赋值(如 arr[0] = newValue)或修改对象已有属性(如 obj.prop = newValue)的操作。你遇到的问题正是典型场景——this.details.forEach(...) 中执行 item.price = item.priceOne,虽然 JavaScript 层面成功赋值,但 Vue 并未追踪该属性变化,因此绑定的 <input v-model="register.price"> 不会自动刷新。
关键误区在于:v-model="register.price" 绑定的是 register 对象的 price,但你的 setPrice(id) 方法却在遍历 this.details 数组并修改其中某个 item.price。如果 register 并非 details 中对应 id 的那个对象引用(例如只是浅拷贝或独立对象),那么修改 details[itemIndex].price 根本不会影响 register.price 的值——这解释了为何“点击页面其他区域后才更新”:可能触发了意外的重渲染或 register 被重新赋值。
✅ 正确做法分两步:
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 确保数据源一致性:确认 register 就是 details 中 id 匹配的那个对象(即 register === this.details.find(d => d.id === register.id))。否则需同步更新 register.price 本身;
- 响应式更新数组项:若 register 确为 details 中的响应式对象,应使用 this.$set 更新整个数组索引位置,而非仅设置对象属性:
setPrice(id) {
const index = this.details.findIndex(detail => detail.id === id);
if (index === -1) return;
const targetItem = this.details[index];
// ✅ 正确:用 $set 替换数组中整个对象(保留响应式)
this.$set(this.details, index, {
...targetItem,
price: targetItem.priceOne
});
}⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- ❌ this.$set(item, 'price', ...) 无效:item 是对象,但 Vue 2 不支持对已存在属性使用 $set 增强响应式(仅对新增属性有效);
- ❌ this.$set(this.details, index, {...}) 是必需的,因为直接 this.details[index] = {...} 无法被 Vue 检测;
- ? 若 register 是独立对象(非 details 引用),请直接更新它:this.register.price = this.register.priceOne(前提是 register 本身是响应式对象);
- ? Vue 3 用户无需此操作:Proxy 机制天然支持深层响应式,item.price = ... 可直接触发更新。
总结:Vue 2 中数组响应式更新的核心原则是——修改数组本身要用 $set,修改对象属性需确保对象本身已被 Vue 观察。始终检查数据引用关系,并优先使用 findIndex + $set 组合保证可靠性。

















