Vuex 商店的 Vue.set() 和 push()

Posted

技术标签:

【中文标题】Vuex 商店的 Vue.set() 和 push()【英文标题】:Vue.set() and push() for Vuex store 【发布时间】:2020-04-28 13:59:53 【问题描述】:

我有一个尝试进行后续更新的 mutator:

state.forms[1].data.metrics.push(newArrayItem)

forms 是一个以1 为键的对象 metrics 是一个数组

由于某种原因,Vuex 成功更新,但组件没有对此更改做出反应。 我在 https://vuejs.org/v2/guide/list.html#Object-Change-Detection-Caveats 上阅读了有关 Vue.set() 的信息

但我不确定如何应用它,或者即使它在这里完全是正确的答案。

感谢您的帮助。

this.$forceUpdate 正在工作,这有点奇怪,因为加载数据的组件使用了computed 属性。

表单状态最初是这样设置的:

const state = 
  forms: 
;

新表单是这样推送的:

state.forms[id] =  formName: payload.formName, data: metrics: [];

新的指标是这样添加的:

var result = getParent(state, payload.path);

result.metricParent.data.metrics.push( id: newMetricId(state, result.formId), ...payload.metric );

【问题讨论】:

你能发布一下状态数据最初是如何设置的吗? 我添加了详细信息。另外,我有一个表单列表,当我在商店中只有一个表单时它起作用了,当事情发生时我添加了“表单”对象。在这里使用动态模块并一次只加载一个表单是一个更好的主意吗? 如果您在任何时候以 Vue 无法观察到的方式改变数据,那么它可能导致不更新视图的突变。见change detection caveats。例如,state.forms[id] = ... 已经是违规行为。 @DecadeMoon 对,我知道,问题是当我需要推送到指标数组时,我不确定如何组合修复(使用 Vue.set 进行数组)通过表单数组访问它。我想我使用动态模块解决了我的问题,但如果你有一个好主意如何组合这些,请告诉我。我什至尝试重新创建数组,推送,然后分配给 state.forms[index],但这也没有用。 【参考方案1】:

您的问题不在于推送到数组。您的问题出在这一行:

state.forms[id] =  formName: payload.formName, data: metrics: [];

因为您在没有使用Vue.set() 的情况下创建state.forms 的新属性,所以表单不是反应式的,因此当您稍后推送到指标数组时,它无法识别。

相反,您应该这样做:

Vue.set(state.forms, id,  formName: payload.formName, data: metrics: []);

然后,推送到state.forms[id].data.metrics 应该会按预期工作。

【讨论】:

【参考方案2】:

Vue 设置响应式数据以查找状态/数据的设置方式,例如,如果在常规组件中定义 x: y: 10 之类的数据并以某种方式更改数据 this.x.y = 20; 它会起作用,因为 Vue 使具有该结构的对象是响应式的(因为是设置结构),如果您尝试这样做,this.x.z = 10; 不起作用,因为“z”不存在,您需要告诉 Vue 您需要使其具有响应性,这是当this.$set(this.x, “z”, 10);进入时,它基本上是在说“让这个数据在位置'z'反应”,之后直接调用this.x.z = ?工作,在vuex中也是如此,使用Vue.set(state.forms, 1, formName: payload.formName, data: metrics: []);之后引用@987654327 @(包括子数据)现在是反应式的!

【讨论】:

当您使用数组并将其设置为初始状态时,每次调用 push 方法都是响应式的,并且不需要手动使用 Vue.set(),在对象中是必要的,因为这是不可能的跟踪 vue 2 中添加的新对象属性

以上是关于Vuex 商店的 Vue.set() 和 push()的主要内容,如果未能解决你的问题,请参考以下文章

测试 VueX 商店

VueX:如何使用嵌套对象构建我的商店

如何使用 Nuxt 和 Jest 在 Vuex 商店测试中访问 this.app 和/或注入插件

如何将 2 个 vuex 商店合并为一个商店

Vuex 商店自动更新

为啥 router.push 不起作用? [Vue 3] [Vuex 4]