取消 vue 组件中的属性更新
Posted
技术标签:
【中文标题】取消 vue 组件中的属性更新【英文标题】:Cancel property update in vue component 【发布时间】:2020-06-12 12:48:19 【问题描述】:我有一个 Vue 组件来更新用户数据
<template>
<form>
... fields to update user property ...
<button class="btn btn-primary" :disabled="!isDirty" @click.prevent="submit">Submit</button>
<button class="btn btn-default" @click.prevent="cancel">Cancel</button>
</form>
</template>
<script>
export default
props: ["user"],
methods:
submit()
this.$emit("formIsSubmitted", true);
,
cancel()
????
;
</script>
当我提交时,父组件中的用户被更新,因为它是一个通过引用传递的对象。 单击取消按钮时,如何将用户属性“重置”为其原始值?
我尝试在 created() 事件中创建一个克隆对象,然后将用户重置为该对象,但随后出现以下错误:
避免直接改变 prop,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“用户”
【问题讨论】:
【参考方案1】:好的,根据@Estradiaz 的回答,我找到了解决方案。 在组件的mounted() 中,我循环遍历用户的所有属性以进行复制。 取消时,我将这些道具复制回用户对象。
export default
props: ["user"],
data: () => (
initUser:
),
mounted()
for (const p in this.user)
this.initUser[p] = this.user[p];
,
methods:
submit()
this.isDirty = false;
this.$emit("formIsSubmitted", true);
,
cancel()
for (const p in this.user)
this.user[p] = this.initUser[p];
this.$emit("formIsSubmitted", `false);
;
【讨论】:
【参考方案2】:所以基本上你想防止改变传递的 props 引用。
一种方法是使用计算的 getter/setter:
...
props: ["user],
data()return
[propname + '_']: ""
.
computed:
[propname]:
get()
return this[propname + '_'] || this.user[propname]
// or call cancel in mounted and just
return this[propname + '_']
,
set(value)
this[propname + '_'] = value
...
cancel()
this[propname] = this.user[propname]
ofc 可以循环假设这等于展平和复制:
created()
this.cancel()
props: ["user"]
data()return flatcopy:
cancel()
Object.entries(this.user)
.forEach(([key,value]) => this.$set(this.flatcopy, key, value)
或某种混合风格(未经测试,但我认为应该以这种方式工作):
function mixin(propname)
return
...
mounted()
if(this.cancel && typeof this.cancel == "function")
const cancel = this.cancel.bind(this)
this.cancel = ()=>
this[propname] = this.user[propname]
cancel()
else
this.$set(this, cancel, (()=>this[propname] = this.user[propname]))
props: ["user],
data()return
[propname + '_']: ""
.
computed:
[propname]:
get()
return this[propname + '_'] || this.user[propname]
// or call cancel in mounted and just
return this[propname + '_']
,
set(value)
this[propname + '_'] = value
usage:
mixins: [mixin('anyname')]
【讨论】:
有没有一种方法可以循环遍历用户对象的数据元素,这样我就不必手动为每个道具名称进行设置?【参考方案3】:你可以这样做
<template>
<form>
... fields to update user property ...
<button class="btn btn-primary" :disabled="!isDirty" @click.prevent="submit">Submit</button>
<button class="btn btn-default" @click.prevent="user=">Cancel</button>
</form>
</template>
<script>
export default
mounted()
this.user = this.userObj;
,
data()
return
user: ,
,
props: ["userObj"],
methods:
submit()
this.$emit("formIsSubmitted", this.user);
,
;
</script>
【讨论】:
这样,user 和 userObj 将是相同的;因此在表单中更新用户也会更新 userObj(= 父组件中的用户)。取消时:用户将重置为 ,但 userObj(因此从父级传递的属性)不会。我想确保父母没有更新。 我一直在我的项目中广泛使用它。但是,如果由于某种原因它对您不起作用,您始终可以在mounted
方法中从您的 prop
显式创建一个新对象。一种方法是JSON.parse(JSON.stringify(this.userObj))
在mounted
;【参考方案4】:
在created
内部,我建议创建一个变量userForm
,将其设置为组件引用的user
。然后,当您提交时,您可以重置userForm
,因为它不是道具。
【讨论】:
以上是关于取消 vue 组件中的属性更新的主要内容,如果未能解决你的问题,请参考以下文章