mapGetters仅在首次加载时出现反应性问题

时间:2019-07-11 09:48:08

标签: javascript vue.js vuex store vue-reactivity

我正在使用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,因此它可以正常工作,因为我希望它从一开始就可以工作...

我做错了什么?为什么在第一次加载时计算值不具有反应性?

感谢您的回答...

4 个答案:

答案 0 :(得分:1)

我认为解决此问题的最佳方法是使用监视程序存储局部变量,然后在改变局部变量时更新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;
}

答案 1 :(得分:0)

请查看以下示例:https://codesandbox.io/s/vuex-store-ne3ol

您的错误是,您在模板中使用this关键字。不应在模板代码中使用this

<input
      type="number"
      value="inputValue"
      @change="$store.dispatch('setInputValue', $event.target.value)"
    >
  

红利提示:使用getter返回默认状态是多余的   如果您只能使用mapState来返回状态。

答案 2 :(得分:0)

模板中有一些小错误。应该是这样:

<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与一个吸气剂和塞特剂一起使用(请参阅https://vuex.vuejs.org/guide/forms.html#two-way-computed-property)。

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

答案 3 :(得分:0)

好的,所以...我发现了问题,它与我的示例无关,我无法真正解释原因,但我将尝试解释如何实现:

在我的商店中,我有下一个方法:

mutations: {
    deleteAppValues(state) {
        state.appValues = null;
    }
}

我在注销时使用了此密码,或者当用户首次进入页面而没有登录时...那么怎么回事?

  1. 用户首先加载页面,商店初始化良好,索引inputValue用空值初始化,因此它存在...
  2. ...但是由于用户未登录,我销毁了商店,所以现在inputValue不等于null,它不存在 ...
  3. 尝试在不存在的内容上使用mapGetters,因此反应性将无法正常工作,因此,如果我调度更改,则会创建存储密钥,但是由于mapGetters是使用不存在的密钥初始化的,它不会听反应...
  4. 重新加载页面后,密钥现在已存在于商店中,因此可以将getter附加到该密钥上,因此现在一切正常...

这正是我的代码出了什么问题的解释……为了使其正常工作,我只是将销毁突变更改为:

mutations: {
    deleteAppValues(state) {
        state.appValues = {
            inputValue: null,
        };
    }
}

像这样,store对象的inputValue键将始终存在,因此吸气剂不会失去反应性...

我试图提出一个简单明了的问题,但这使我忘记了代码的不好部分,对不起。