计算的Vue组件无反应

时间:2019-03-22 14:40:33

标签: vue.js

我有2个组件OperatorsList和OperatorButton。 当然,OperatorsList包含我的按钮,当我单击一个按钮时,我只是想更新一些数据:

  • 我用operator.id发出 select
  • 此事件由OperatorList组件捕获,该组件在商店中调用 setSelectedOperator

    1. 这里的第一个问题是,在Vue工具中,我可以在Vuex选项卡上看到商店实时更新,但是在“组件”选项卡上,直到单击树中的另一个节点,操作员计算的对象才会更新:不知道这是Vue工具中的显示问题还是实际的数据更新问题。

    2. 但是,完成后,我在Vue根元素上有另一个计算的属性,称为 selectedOperator ,该属性应该返回... selected运算符:其值始终保持为null,我不能找出原因。

    3. 最后,在按钮上,我有一个v-bind:class,当operator.selected属性为true时应该更新:即使我看到该属性设置为true,它也不会更新。

我刚刚开始使用Vue,我敢肯定我做错了什么,但是呢? 在使用Vuex和道具之前,我遇到了同样的问题。

这是我的OperatorList代码:

<template>
    <div>
        <div class="conthdr">Operator</div>
        <div>
            <operator-button v-for="operator in operators" :op="operator.id" 
            :key="operator.id" @select="selectOp"></operator-button>
        </div>
    </div>
</template>
<script>
    import OperatorButton from './OperatorButton';
    export default {
        name: 'operators-list',
        components : {
            'operator-button': OperatorButton
        },
        computed : {
            operators() { return this.$store.getters.operators },
            selected() {
                this.operators.forEach(op =>{
                    if (op.selected) return op;
                });
                return null;
            },
        },
        methods : {
            selectOp(arg) {
                this.$store.commit('setSelectedOperator', arg);
            }            
        },
    }
</script>

OperatorButton代码为

<template>
    <span>
        <button type="button" v-bind:class="{ sel: operator.selected }" 
         @click="$emit('select', {'id':operator.id})">
            {{ operateur.name }}
        </button>
    </span>
</template>
<script>
    export default {
        name: 'operator-button',
        props : ['op'],
        computed : {
            operator() {
                return this.$store.getters.operateurById(this.op);
            }
        },
    }
</script>
<style scoped>
    .sel{
        background-color : yellow;
    }
</style>

最后我的app.js看起来像这样:

window.Vue = require('vue');
import Vuex from 'vuex';
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';

const store = new Vuex.Store({
    state: {    
        periods : [],
    },
    mutations: {
        setInitialData (state, payload) {
            state.periods = payload;
        },
        setSelectedOperator(state, payload) {
            this.getters.operateurs.forEach( op => {
                op.selected = (op.id==payload.id)
            })
        },
    },
    getters : { 
       operators : (state) => { 
            if (Array.isArray(state.periods)) 
            {
                let ops = state.periods
                .map( item => {
                    return item.operators
                }).flat();
                ops.forEach(op => {
                    // op.selected=false; //replaced after Radu Diță answer by next line : 
                    if (ops.selected === undefined) op.selected=false;
                })
                return ops;
            }
        },
        operatorById : (state, getters) => (id) => {
            return getters.operators.find(operator => operator.id==id);
        },
    }
});

import Chrono from './components/Chrono.vue';
var app = new Vue({
            el: '#app',
            store,
            components : { Chrono },
            mounted () {
               this.$store.commit('setInitialData',
                    JSON.parse(this.$el.attributes.initialdata.value));
            },
            computed: {
                            ...mapState(['periods']),
                            ...mapGetters(['operators', 'operatorById']),
                            selectedOperator(){
                                this.$store.getters.operators.forEach(op =>{
                                    if (op.selected) return op;
                                });
                                return null;
                            }

            },
        });

2 个答案:

答案 0 :(得分:2)

您在vuex中为operators获得的吸气剂始终设置为false。

operators : (state) => { 
        if (Array.isArray(state.periods)) 
        {
            let ops = state.periods
            .map( item => {
                return item.operators
            }).flat();
            ops.forEach(op => {
                op.selected=false;
            })
            return ops;
        }
    }

我猜您是为了初始化而做的,但是放起来很不好,因为您永远不会从那个吸气剂中得到一个选定的运算符。只需将其移动到适当的突变即可。 setInitialData似乎是正确的地方。

答案 1 :(得分:0)

最后,我发现了问题所在: $el.attributes.initialdata.value来自一个API,它包含的操作符对象没有selected属性,因此我在设置数据之后将其添加,并且它没有反应。 我只是在服务器端添加了此属性,然后再转换为JSON并将其发送给Vue,删除了Radu Diță指出的代码,因为它现在已无用,并且可以正常工作。