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)。

我的怀疑是,当您重新加载触发更改事件的页面时,因为它模糊了字段。

【讨论】:

这完全是我的错,我在这里写的代码不是很好......但它没有改变任何东西......我真正的问题确实来自&lt;select&gt;标签,但我想要不写选项和所有内容,我尝试了输入和相同的问题,所以我决定将输入方式放在我的问题中以更加协调......【参考方案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 的反应性问题仅在第一次加载时的主要内容,如果未能解决你的问题,请参考以下文章

Vue 仅在组件加载时绑定类

仅在初始渲染后反应 CSS 动画

如何在页面加载时在反应打字稿中设置可见性

Angular 反应复选框仅在第一次单击后正确切换

仅在第一次加载 Angular 网页时使用 Safari 接收 401 状态

jQgrid“loadComplete”事件仅在第一次加载时才被调用