You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue 2.0对象响应式问题:点击撤销按钮UI未同步初始值

问题出在哪?
  1. 父组件初始化写错了:mounted里的_cloneDeep(item)应该是_cloneDeep(this.initialItem),不然item根本没定义。
  2. 子组件的itemDetail只会在组件创建时赋值一次父组件的item,之后父组件改currentItem,子组件的itemDetail不会自动跟着变——Vue的data选项只在实例初始化时执行一次,后续prop变了它也不会主动更新。
  3. 你直接把initialItem赋值给currentItem,这是引用传递,之后改currentItem会把原始的initialItem也改了,等于初始值被污染了。
怎么改?

先把父组件的逻辑修对

// 父组件的data、钩子和方法
data: function() {
  return {
    initialItem: { name: "item", size: 10, description: "some text" },
    currentItem: null
  };
},
mounted() {
  // 初始化时深拷贝initialItem,避免后续修改污染原始值
  this.currentItem = _cloneDeep(this.initialItem);
},
methods: {
  updateItem(item) {
    this.currentItem = _cloneDeep(item); // 可选:深拷贝防止子组件修改直接影响父组件
  },
  discardChanges() {
    // 必须深拷贝initialItem,生成新的对象引用,才能触发Vue的响应式更新
    this.currentItem = _cloneDeep(this.initialItem);
  }
}

子组件加个监听,同步父组件的变化

子组件需要盯着父组件传过来的item,一旦父组件的currentItem变了,就重新更新自己的itemDetail:

<!-- 子组件模板 -->
<input :value.sync="itemDetail.name" @input="$emit('set-item', itemDetail)" />
<!-- 其他输入框照猫画虎 -->

<script>
import _cloneDeep from 'lodash/cloneDeep';

export const ChildComponent = {
  props: {
    item: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      // 初始化时深拷贝父组件的item,别直接用引用
      itemDetail: _cloneDeep(this.item)
    };
  },
  watch: {
    // 监听item prop的变化,父组件一更新就同步过来
    item(newItem) {
      this.itemDetail = _cloneDeep(newItem);
    }
  }
};
</script>

为啥之前的方法没用?

  • Vue.set:这个是给对象加新属性用的,你这是替换整个对象,用不上。
  • this.$forceUpdate():强制更新也没用,因为子组件的itemDetail根本没拿到新值,更新了也是旧数据。
  • currentItem先设为null再赋值initialItem:虽然换了引用,但子组件没监听prop变化,还是用的旧的itemDetail,所以UI不会变。

内容的提问来源于stack exchange,提问作者pmpc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 18:20:08