与 Vuex、axios 和多个组件实例进行封装数据共享

Posted

技术标签:

【中文标题】与 Vuex、axios 和多个组件实例进行封装数据共享【英文标题】:Capsuled data sharing with Vuex, axios & several component instances 【发布时间】:2021-02-26 17:19:40 【问题描述】:

我有一个组件QuestionContainer.vue 有几个问题(输入表单)。使用名为 keyUpRoutine(questionkey) 的方法对每个用户给出的答案(用户输入)进行实时验证 (@keyup.prevent="keyUpRoutine(questionkey)")。如果所有答案都有效,我会执行一致性检查:

在 QuestionContainer.vue 中:

keyUpRoutine(questionkey) 

    var value = event.target.value;
    var question = this.questions[questionkey];

    question.validated = this.validate(question, value) ?  true : false;

    this.allConditioncomplied() 
        ? this.$store.dispatch("checkObligationConsistency",  someData )
        : this.questionState = 'default';
        // this.questionState must be changed by Vuex' action (app.js) checkObligationConsistency()

app.js 中的操作:

checkObligationConsistency(context, obligation) 
    context.commit("SET_OBLIGATION_STATE", "checking");
    axios
        .post("/DataCheck/checkObligationConsistency", obligation)
        .then(function(response) 

            context.commit("SET_OBLIGATION_STATE", "valid");
            
            if (store.state.modalType == "QuestionPack") 
                context.commit("SET_QUESTION_STATE", "add");
                // In QuestionContainer.vue, this.questionState must be set to 'add'
                // Incorrect approach: store.state.questionState = "add";
             else 
                context.commit("SET_QUESTION_STATE", "submit");
                // In QuestionContainer.vue, this.questionState must be set to 'submit'                
                // Incorrect approach: store.state.questionState = "submit";
            

        )
        .catch(function(error) 
            console.log(error);
            context.commit("SET_OBLIGATION_STATE", "invalid");

        );

问题的症结:组件QuestionContainer.vue可能存在两次(常规,有时在模态div中),因此使用Vuex状态将不起作用,因为必须在每个组件中隔离状态.

有没有办法返回 QuestionContainer.vue 的 questionState 的新值并将其封装在每个组件中?

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,我必须存储同一组件的多个实例的状态。因此,目前您的突变会更新商店中的单个属性。我的方法不是这样做,而是为此状态创建一个对象数组。例如,你的突变应该像这样工作: App.js

context.commit("SET_OBLIGATION_STATE", index: 0, value: "valid");

store/state.js

// You can instantiate it with all your instances of this component or add them dynamically
 obligationState: [  value: "valid"  ] 

store/mutation.js

SET_OBLIGATION_STATE(state, payload) 
    Vue.set(state.obligationState, payload.index, payload.value)
,

QuestionContainer.vue

// You can pass here the index of your component instance and then 'checkObligationConsistency' action will know which instance state to update
this.$store.dispatch("checkObligationConsistency",  someData, index )

【讨论】:

请注意 state.obligationState[payload.index] = payload.value; 不会被 Vue 的反应性选中。请改用Vue.set(this.obligationState, payload.index, payload.value) @DigitalDrifter 是的,我忘了提这个。谢谢! @DigitalDrifter 实际上在 Vue v3 中我认为它可能在没有 Vue.set() 的情况下工作,因为反应系统是用 Proxy 重写的。你觉得怎么样,到目前为止你有没有尝试过? 谢谢@NikolayYankov!您的方法取得了成功:-)

以上是关于与 Vuex、axios 和多个组件实例进行封装数据共享的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js / Vuex + axios 发送多个 PUT 请求

Vue+Vuex 实现全局统一错误提示

Vue之vuex和axios

vue-cli 初始化创建 vue2.9.6 项目路由守卫封装axiosvuex

axios网络请求基本使用配置使用(全局axios和局部axios实例)模块封装axios拦截器

动作发送到 Vuex 后如何将数据传递给组件?