在参加计算机设计大赛做作品的时候遇到的一个困难,花了挺长时间才解决,在这里做个记录。

一、这里先介绍如何CDN引入ECharts

在需要用到ECharts的界面加入

<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.1/dist/echarts.js"></script>

即可,或者先下载好这个文件,src改为这个文件的相对路径。

二、以南丁格尔玫瑰图为例(我的项目是用了这个图表)

先看ECharts示例完整代码

示例是直接在script中演示效果,所有数据都是写死

而我们用Vue的目的就是实现根据请求后端返回的数据对视图层进行动态的渲染,保证每次请求返回的数据都能被正确地渲染到视图层上。

html:

 <div id="illegal" style="width: 1000;height: 650px;"> </div>

Vue实例对象的data中写上要被动态渲染的数据:

data:{
    viewBehavior: {
        转让通行证: 0,
        伪造通行证: 0,
        售卖通行证: 0,
        拆卸通行证: 0,
        借予他人使用: 0,
        故意损坏或涂鸦通行证: 0,
        行驶速度过快: 0,
        未佩戴安全头盔: 0,
        未在规定区域停放: 0,
        未在规定区域充电: 0,
    }
}

然后这些数据都是通过mounted钩子函数去执行methods封装了ajax请求的函数getViolations返回回来的。

methods:{
            //获取某违规情况
            getViolations(stringValue) { // 参数stringValue 如 “行驶速度过快”
                var that = this;
                $.ajax({
                    url: '接口地址',
                    data: {
                        key: "behavior",
                        value: stringValue
                    },
                    // async: false,
                    type: "POST",
                    success(res) {
                        if (res.error_code == 0) {
                            Vue.set(that.viewBehavior, stringValue, res.length);
                            console.log(stringValue + ":" + that.viewBehavior[stringValue]);
                        } else if (res.error_code == 1) {
                            console.log(res.msg);
                        }
                    },
                    error() {
                        that.$Message.error({
                            content: res.msg
                        });
                    }
                })
            },}

因为我写的接口是根据key:value查询来返回数据,

所以在mounted钩子函数用for循环去请求viewBehavior中各项数据(注意values数组各元素要对应Vue实例对象data里的viewBehavior对象的属性(左值))

mounted:{
     var values = ['转让通行证', '伪造通行证', '售卖通行证', '拆卸通行证', '借予他人使用',
                '故意损坏或涂鸦通行证', '行驶速度过快', '未佩戴安全头盔', '未在规定区域停放', '未在规定区域充电'
            ];
     // 获取各类违规情况的人数
     for (var i = 0; i < values.length; i++) {
         that.getViolations(values[i]); //调用包含ajax的获取数据的函数
     }
}

然后各种百度后其实都没有找到合理的解决方案。就自己仔细琢磨了一下示例代码。

我的第一次错误的做法:就是直接把ECharts一大段示例代码直接搬到Vue实例对象的mounted钩子函数中,只把从mounted钩子函数中var出来的option中的series中的data中的各项value赋值为Vue实例对象data中viewBehavior中的各值

data: [
    {value: that.viewBehavior['转让通行证'],name: '转让通行证'},
    {value: that.viewBehavior['伪造通行证'],name: '伪造通行证'}, 
    {value: that.viewBehavior['售卖通行证'],name: '售卖通行证'}, 
    {value: that.viewBehavior['拆卸通行证'],name: '拆卸通行证'}, 
    {value: that.viewBehavior['借予他人使用'],name: '借予他人使用'},
    {value: that.viewBehavior['故意损坏或涂鸦通行证'],name: '故意损坏、涂鸦通行证'}, 
    {value: that.viewBehavior['行驶速度过快'],name: '行驶速度过快'}, 
    {value: that.viewBehavior['未佩戴安全头盔'],name: '未佩戴安全头盔'},
    {value: that.viewBehavior['未在规定区域停放'],name: '未在规定区域停放'}, 
    {value: that.viewBehavior['未在规定区域充电'],name: '未在规定区域充电'}
],

然而,页面在加载的时候,老是渲染不出正确的后台数据(有时候全是0,有时候很多项是0)

于是尝试

setTimeout(function(){
    option && myChart.setOption(option);
},4000)

去延迟myChart的渲染。结果发现数据能大概率(注意是概率)正确渲染了。但是这种方法是不能根除问题的!再缩短一下延迟时间比如1秒,它又不能正确渲染了。

那就找到问题所在了:

数据在还没请求完毕,视图就被渲染,而且viewBehavior各属性默认值是0。

那怎么办?当即就想到等ajax请求完数据了,再往下执行代码呗。

然后我就把ajax的async配置项设为false(同步请求)

async:false

后台返回的数据的的确确100%能正确渲染到视图层了,但是加载速度实在是太慢了!,加载没完成什么都动不了,当我频繁切换页面的时候,点这个用到ECharts的页面就会因为ajax请求卡很久。

隔了一个星期,又想到一个不规范的方法,把setTimeout改为setInterval。对EChart视图进行定时渲染,每隔1秒渲染一遍。(视图会每隔1s更新一次,第一次渲染的数据也是很难完全请求完毕的

setInterval(function(){
    option && myChart.setOption(option);
},1000)

这种方法的确可以保证最后的视图能根据最后的viewSort数据被正确渲染,但是正确渲染后,它还在不断地渲染(虽然用户看不出来,但是这种做法是作为一个合格程序员的低级做法,也没有用到Vue正确的MVVM原理)。

随后在床上睡觉突然来了灵感

正确做法:

每次ajax请求会修改Vue实例对象中的data中的viewBehavior中某属性的值。

那我们就深度监视viewBehavior中某属性被修改的时候,去重新渲染视图就好了呀!

watch: {
    viewBehavior: {
        deep: true,
        handler() {
            //保存一下this
            var that = this;
            var chartDom = document.getElementById('illegal');
            var myChart = echarts.init(chartDom);
            /*echarts start*/
            //option 开始
            /* 指定图表的配置项和数据 */
            var option = {
                legend: { //图例组件
                    bottom: '10px', //图例组件(即颜色分类说明图标)离容器上侧的距离
                },
                toolbox: { //工具栏组件相关行为
                    show: true,
                    feature: {
                        mark: {
                            show: true
                        },
                        restore: {
                            show: true
                        },
                        // 还原
                        saveAsImage: {
                            show: true
                        } //保存为图
                    }
                },
                title: {
                    text: '各类违规情况人数及其占比',
                    top: '30px',
                    left: 'center'
                },
                // series start
                series: [ //“事件”
                        {
                            name: 'Nightingale Chart', //访问来源
                            type: 'pie', //饼状图
                            radius: [50, 200],
                            center: ['50%', '50%'],
                            roseType: 'area',
                            /*'radius' 扇区圆心角展现数据的百分比,半径展现数据的大小。
                            'area' 所有扇区圆心角相同,仅通过半径展现数据大小。*/
                            itemStyle: {
                                normal: {
                                    label: {
                                        show: true,
                                        formatter: '{b} : {c} ({d}%)'
                                    },
                                    labelLine: {
                                        show: true
                                    },
                                    borderRadius: 8,
                                },
                            },
                            data: [{
                                value: that.viewBehavior['转让通行证'],
                                name: '转让通行证'
                            }, {
                                value: that.viewBehavior['伪造通行证'],
                                name: '伪造通行证'
                            }, {
                                value: that.viewBehavior['售卖通行证'],
                                name: '售卖通行证'
                            }, {
                                value: that.viewBehavior['拆卸通行证'],
                                name: '拆卸通行证'
                            }, {
                                value: that.viewBehavior['借予他人使用'],
                                name: '借予他人使用'
                            }, {
                                value: that.viewBehavior['故意损坏或涂鸦通行证'],
                                name: '故意损坏、涂鸦通行证'
                            }, {
                                value: that.viewBehavior['行驶速度过快'],
                                name: '行驶速度过快'
                            }, {
                                value: that.viewBehavior['未佩戴安全头盔'],
                                name: '未佩戴安全头盔'
                            }, {
                                value: that.viewBehavior['未在规定区域停放'],
                                name: '未在规定区域停放'
                            }, {
                                value: that.viewBehavior['未在规定区域充电'],
                                name: '未在规定区域充电'
                            }, ],
                        },
                    ]
                    // series end
            };
            //option结束
            // echarts大饼图end

            // 渲染视图
            option && myChart.setOption(option);
        }
    }
},

现在ajax能异步请求,又能根据显示后台请求返回的数据正确渲染到视图了!

至此,感谢阅读我的文章,如果对你有用,请点个赞赞 ❤

Logo

前往低代码交流专区

更多推荐