javascript - 状态变化时更新谷歌图表 - vuex

标签 javascript vue.js google-visualization vue-component vuex

我正在做一个报告页面,其中会出现几个图表。当您进入该页面时,它会通过API请求接收所有默认信息。我们的想法是,之后允许用户根据输入选择一些过滤器。

示例:初始 - 所有结果/带过滤器 - 一些结果。

为了实现这一点,我使用 vuejs 来制作组件,使用 vuex 来保存信息,并使用 google 图表来制作图表。

我的问题是,当我实现某些过滤器时,即使状态更新,图形也不会更新。我放置了一个观察者,以检查状态是否发生变化,但仅在创建时才进入。

我的代码-

vuex-

import axios from 'axios';

const state = {
    dataChart: {}
}

const mutations = {
    'ADD_DATA_CHART'(state, data) {
        state.dataChart[data.key] = [];

        [].forEach.call(data.states, (s, i) => {
            let obj = {};
            obj.name = s;
            obj.data = [];

            [].forEach.call(data.value, d => {
                obj.data.push([d.name, d[data.keys[i]].toFixed(2)]);
            });
            state.dataChart[data.key].push(obj);
        });
    }
}

const actions = {
    fetchReporting({state, commit}, response) {
        axios.post(response.endpoint, response.formData)
            .then(({data}) => {
                commit('ADD_DATA_CHART', {key: response.chart, value: data, states: response.states, keys: response.keys})
            }).catch(err => {
                console.log(err);
            });
    }
}

const getters = {
     dataChart: state => state.dataChart
}


export default {
    state,
    mutations,
    actions,
    getters
}

组件-

<template>
    <div class="box-content-white">
        <div class="title">Chart</div>
        <div id="stackedChart"></div>
    </div>
</template>
<script>
    import { mapGetters } from 'vuex';
    import { mapActions } from 'vuex';

    export default {
        props: {
            endpoint: String,
            chart: String,
            states: Array,
            keys: Array
        },
        data() {
            return {
                 data: []
            }
        },
        methods: {
            ...mapActions({
                fetchReporting: 'fetchReporting'
            }),
            loadChart() {
                google.charts.load('current', {'packages':['corechart'],'language': 'pt'});
                google.charts.setOnLoadCallback(this.drawChart);

            },
            drawChart() {
                var stackedChart = new google.visualization.DataTable();
                stackedChart.addColumn('string', this.states[0]);
                stackedChart.addColumn('number', this.states[1]);
                stackedChart.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
                stackedChart.addColumn('number', this.states[2]);
                stackedChart.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
                stackedChart.addColumn('number', this.states[3]);
                stackedChart.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});

                stackedChart.addRows(this.data);

                var options = {
                        width: '100%',
                        height: 600,
                        chartArea: {width: '90%', height: '60%', left: 120},
                        isStacked: true,
                        colors: ['#e6a8b9','#cc5173', '#901c3c'],
                        tooltip: { isHtml: true },
                        legend: { position: 'bottom', alignment: 'start' },
                        animation: {
                            duration: 1000,
                            easing: 'out',
                            startup: true
                        }
                    };

                new google.visualization.ColumnChart(document.getElementById('stackedChart')).draw(stackedChart, options);
            },
            drawHtmlTooltip(message,  message2,  message3,  message4, url) {
                return `<div class="content">
                            <div class="img">
                                <img src="url" alt="Cliente">
                            </div>
                            <div class="text">
                                <div><span class="info">Message</div>
                                <div><span class="info">Message2</div>
                                <div><span class="info">Message3</div>
                                <div><span class="info">Message4</div>
                            </div>
                        </div>`;
            },
            mountData() {
                [].forEach.call(this.dataChart[this.chart], d => {

                    let htmlTooltip = this.drawHtmlTooltip(message, message2, message3, message4, url);
                    this.data.push([ // * it is necessary to repeat the tooltip, so that it is uniform in all bars
                        d.name,
                        parseInt(value),
                        htmlTooltip,
                        parseInt(value2),
                        htmlTooltip,
                        parseInt(value3),
                        htmlTooltip
                    ]);
                });

                this.loadChart();
            }
        },
        mounted() {
            this.fetchReporting({endpoint: this.endpoint, chart: this.chart, formData: { state: 'negotiation' }})
            .then(response => {
                this.mountData();
            }, error => {
                console.log(error)
            });

        },
        computed: {
            ...mapGetters({
                dataChart: 'dataChart'
            })
        },
        watch: {
            dataChart:  {
                immediate: true,              // so this runs initially
                deep: true,                   // so it detects changes to properties only
                handler(newVal, oldVal) {
                    console.log('selectedItem changed!', oldVal, '-->', newVal);
                }
            }
        }
    }
</script>

我没有解决方案,您有什么建议来解决这个问题吗?

最佳答案

要使 state.dataChart 具有反应性,您需要将其分配给新的对象引用。

ES6 语法:

const mutations = {
    'ADD_DATA_CHART'(state, data) {
        var newDataItem = []
        [].forEach.call(data.states, (s, i) => {
            let obj = {};
            obj.name = s;
            obj.data = [];

            [].forEach.call(data.value, d => {
                obj.data.push([d.name, d[data.keys[i]].toFixed(2)]);
            });
            newDataItem.push(obj);
        });
        state.dataChart = {
          ...state.dataChart,
          [data.key]: newDataItem
        }
    }
}

关于javascript - 状态变化时更新谷歌图表 - vuex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51048165/

相关文章:

javascript - 运行 jasmine 测试时,我怎么知道我是在 describe block 、beforeEach block 还是 it block 中?

javascript - 在任何点击事件处理程序之前调用函数

javascript - 如何使用应用脚本根据单元格值修改谷歌表格图表颜色

javascript - Google Charts 柱形图在打开时给出对象 [对象数组] 没有方法 'getColumnType'

javascript - 谷歌饼图未显示在模式弹出窗口中

javascript - 正则表达式 - 从第二次出现到倒数第二次出现

javascript - 如何在html文本框中显示google maps api标记的经纬度

vue.js - Nuxt 生成不关闭标签

vue.js - 如何正确地将Bootstrap5的Masonry加载到Nuxt中?

vue.js - 手动输入日期和/或使用日历 vuetify