Vue 2.0对象响应式问题:点击撤销按钮UI未同步初始值
问题出在哪?
- 父组件初始化写错了:
mounted里的_cloneDeep(item)应该是_cloneDeep(this.initialItem),不然item根本没定义。 - 子组件的
itemDetail只会在组件创建时赋值一次父组件的item,之后父组件改currentItem,子组件的itemDetail不会自动跟着变——Vue的data选项只在实例初始化时执行一次,后续prop变了它也不会主动更新。 - 你直接把
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
相关产品推荐
相关产品推荐

