mapGetters 的反应性问题仅在第一次加载时
Posted
技术标签:
【中文标题】mapGetters 的反应性问题仅在第一次加载时【英文标题】:Reactivity problem with mapGetters only on first load 【发布时间】:2019-11-21 00:09:52 【问题描述】:我正在使用来自 VueX 的 mapGetters
助手,但我仅在页面的第一次加载时遇到了一些问题,它不是反应式的......
让我告诉你:
触发更改的我的 html 模板:
<input type="number" value="this.inputValue" @change="this.$store.dispatch('setInputValue', $event.target.value)">
我的商店收到了价值
state:
appValues:
inputValue: null
,
,
getters:
getInputValue: (state) =>
return state.appValues.inputValue;
,
,
mutations:
setInputValue(state, value)
state.appValues.inputValue = value;
,
,
actions:
setInputValue(context, payload)
return new Promise((resolve, reject) =>
context.commit('setInputValue', payload);
resolve();
);
,
然后我的组件监听商店:
import mapGetters from 'vuex';
computed:
...mapGetters(
inputValue: 'getInputValue',
),
watch:
inputValue:
deep: true,
immediate: true,
handler(nVal, oVal)
console.log("inputValue", nVal, oVal);
,
所以现在,当我第一次加载页面时,我得到了这个 console.log "inputValue" null undefined
,这是完全正常的,因为我的商店里什么都没有,它给了我默认值 null。
但现在是奇怪的部分。我开始更改输入值,但我的控制台中没有任何内容。什么都没有动……
然后我重新加载页面并在加载时得到这个 console.log "inputValue" 5 undefined
(5 是我之前输入的值)所以你可以看到,当我之前更改输入时,它很好地保持了值在商店中,但计算的值没有自行更新...
现在,当我更改输入的值时,我的控制台日志是这样的 "inputValue" 7 5
,所以它可以像我希望的那样从一开始就工作......
我做错了什么?为什么在第一次加载时计算值没有反应?
感谢您的回答...
【问题讨论】:
【参考方案1】:好的,所以...我发现了问题,这与我的示例无关,我无法真正解释原因,但我会尝试解释原因:
在我的商店我有下一个方法:
mutations:
deleteAppValues(state)
state.appValues = null;
我在注销时使用了这个,或者当用户第一次进入页面但没有登录时......那么发生了什么?
-
User首次加载页面,store初始化良好,索引
inputValue
初始化为null值,所以存在...
...但是由于用户没有登录,我销毁了存储,所以现在 inputValue 不等于 null,它只是不存在...
尝试在不存在的东西上使用mapGetters
,反应将不起作用,所以如果我发送更改,将创建存储键,但由于 mapGetters 使用不存在的键初始化,它不听反应...
重新加载页面后,密钥现在存在于存储中,因此可以将 getter 附加到它,所以现在一切正常...
这正是我的代码出了什么问题的解释......所以为了让它正常工作,我只是将我的破坏突变更改为:
mutations:
deleteAppValues(state)
state.appValues =
inputValue: null,
;
这样,store 对象的 inputValue 键将一直存在,因此 getter 不会失去响应性...
我试图提出一个简单简洁的问题,但这让我忘记了我的代码中不好的部分,抱歉。
【讨论】:
【参考方案2】:模板中有一些小错误。应该是这样的:
<input type="number" :value="inputValue" @change="$store.dispatch('setInputValue', $event.target.value)">
我已经在几个地方删除了this.
,并在value
前面放置了一个:
。一旦我进行了这些更改,一切都会按预期工作。 this.$store
导致我使用 Vue 2.6.10 时出现控制台错误。
我要补充一点,您正在使用change
事件。这是标准的 DOM change
事件,在字段模糊之前不会触发。因此,如果您只是开始输入,您将不会看到控制台中发生任何事情。如果您希望它在每次击键时更新,您最好使用input
。或者,您可以将 v-model
与 getter 和 setter 一起使用(请参阅 https://vuex.vuejs.org/guide/forms.html#two-way-computed-property)。
我的怀疑是,当您重新加载触发更改事件的页面时,因为它模糊了字段。
【讨论】:
这完全是我的错,我在这里写的代码不是很好......但它没有改变任何东西......我真正的问题确实来自<select>
标签,但我想要不写选项和所有内容,我尝试了输入和相同的问题,所以我决定将输入方式放在我的问题中以更加协调......【参考方案3】:
请看一下这个示例:https://codesandbox.io/s/vuex-store-ne3ol
您的错误是,您在模板中使用了this
关键字。不应在模板代码中使用this
。
<input
type="number"
value="inputValue"
@change="$store.dispatch('setInputValue', $event.target.value)"
>
额外提示:使用 getter 返回默认状态是多余的 如果您可以使用
mapState
返回状态。
【讨论】:
感谢您的回答,但在我的情况下它不起作用,它根本不会改变任何东西...... -_- 哦,顺便说一句,如果我使用 mapGetter 这是因为在我的真实项目(我给出的代码只是我所有代码的简历)getter很重要,因为我可以做出一些我在State中做不到的条件和逻辑 @SimonTrichereau 很酷,如果你想使用getter 来获取条件数据是状态。然后就好了。您能否在 codepen 或 codesandbox 中创建一个代码示例,以便我帮助您解决问题。【参考方案4】:我认为解决这个问题最好的办法是用一个watcher存储一个局部变量,然后当local改变时更新vuex:
在您的组件上:
<input type="number" v-model="value">
data()
return
value: ''
;
,
computed:
...mapGetters(
inputValue: 'getInputValue'
)
watch:
value(value)
this.$store.dispatch('setInputValue', value);
,
inputValue(value)
console.log('inputValue', value);
,
created()
// set the initial value to be the same as the one in vuex
this.value = this.inputValue;
【讨论】:
谢谢,我已经这样做了,是的,它有效,但问题更像是我的商店中有大量变量,所以如果我必须复制它们中的每一个,那将是浪费时间...而且 mapGetters 应该可以正常工作...以上是关于mapGetters 的反应性问题仅在第一次加载时的主要内容,如果未能解决你的问题,请参考以下文章