首页 前端知识 vue,echarts组件封装动态复用生成N个

vue,echarts组件封装动态复用生成N个

2024-09-29 22:09:16 前端知识 前端哥 706 842 我要收藏

由于我们在做项目的时候相同的echarts可能会复用多次,并且可能会在一个页面展示多个echarts。话不多说,了解一下我的需求场景,直接上图
最终效果图
需求:根据开始日期,结束日期(日期选择范围限制在一周内)进行查询不同类型的数据

解决思路:

把每一个echarts封装成一个单独的组件,通过查询的数据直接渲染多个echarts不就完了吗------------------理想很丰满,显示很骨感 哈哈哈

第一步:echarts作为子组件

子组件的代码没什么要说的,这里把重要代码截图放在下面,其中sourceData就是父组件传递过来的数据
子组件核心代码

<!-- 封装echarts组件 -->
<template>
    <div>
        <div id="echart" ref="main" style="width:400px;height:270px"></div>
    </div>
</template>
<script>
import * as echarts from 'echarts';
export default{
    props:{
        //传进来需要显示的数据
        data:{
            type:Object,
            default:{}
        }
    },
    data(){
        return{
        }
    },
    watch:{
        data:{
            deep:true,
            handler(newVal,oldVal){
                
                console.log(newVal,oldVal,"+++++");
                this.$nextTick(()=>{
                    this.resetEchart()
                })
            }
        }
    },
    mounted(){
        
        this.$nextTick(()=>{
            this.resetEchart()
        })
        
    },
    created(){
        
        this.$nextTick(()=>{
           this.resetEchart()
        })
    },
    methods:{
        initChart(sourceData) {
            //console.log(sourceData,"+++++++");
            let getchart = echarts.init(this.$refs.main);
            var  option = {
                legend: {},
                tooltip: {},
                dataset: sourceData,
                // 声明一个 X 轴,类目轴(category)。默认情况下,类目轴对应到 dataset 第一列。
                xAxis: { type: 'category' },
                // 声明一个 Y 轴,数值轴。
                yAxis: {},
                // 声明多个 bar 系列,默认情况下,每个系列会自动对应到 dataset 的每一列。
                series: [{ type: 'bar' }, { type: 'bar' }]
            };
            getchart.setOption(option);
            //随着屏幕大小调节图表
            window.addEventListener("resize", () => {
                getchart.resize();
            });
        },
        resetEchart(){
            let a = document.getElementById("echart");
            a.removeAttribute('_echarts_instance_');
            this.initChart(this.data)
        }

    }
}
</script>

看过echarts官网都知道sourceData的结构是有要求的,不然echarts图表不能正确展示(这里结构自行到官网查看)
所以这里要和后端协商好,如果后端把返回的数据都处理以上结构那么前端直接渲染就可以,但是就怕后端不能处理,呜呜呜

那么前端的工作量就大了 啊啊啊

下面看后端返回给我的数据结构
在这里插入图片描述

第二步:处理数据
把后端返回给我的数据结构处理成echarts官网source的结构
处理后的数据结构
数据处理的核心代码如下图
数据处理的核心代码

formateEchartData(){
                const echartDataObj = {};
                const obj = [];
                const newArr = []
                this.echartData.forEach(val=>{
                    obj.push([val.day,val.qnjrs,val.jrs]);
                    this.$set(echartDataObj,val.item,{
                        name:val.name,
                        option:{
                            dimensions: ['product', '2022', '2023'],
                            source:[]
                        }})
                })
                console.log(obj,"ooooooooooo");
                for(var i=0;i<obj.length;i+=this.dateCount){
                    newArr.push(obj.slice(i,i+this.dateCount));
                }
                console.log(newArr,"aaaaaaa");
                var item = 0;
                for(var key in echartDataObj){
                    //console.log(key, "key");
                    echartDataObj[key].option.source = newArr[item]
                    item++
                } 
                this.NewChartData = echartDataObj
                console.log(this.NewChartData,"重新赋值");
            }

最后附上父组件的全部代码

<!-- 门诊部数据统计 -->
<template>
    <div class="app-container">
        <el-row>
            <el-col class="card-box">
                <el-card>
                    <div class="block">
                        <div class="demonstration">*查询日期范围不能超过一周</div>
                        <el-form :inline="true" :model="ruleForm"  :rules="rules"  ref="ruleForm">
                            <el-form-item label="开始日期" prop="ksrq">
                                <el-date-picker
                                :picker-options="pickerOptionsStart"
                                clearable
                                size="small"
                                style="width: 200px"
                                v-model="ruleForm.ksrq"
                                format="yyyy-MM-dd"
                                value-format="yyyy-MM-dd"
                                type="date"
                                placeholder="选择开始日期"
                                >
                                </el-date-picker>
                            </el-form-item>
                            <el-form-item label="结束日期" prop="jsrq">
                                <el-date-picker
                                :picker-options="pickerOptionsEnd"
                                clearable
                                size="small"
                                style="width: 200px"
                                v-model="ruleForm.jsrq"
                                format="yyyy-MM-dd"
                                value-format="yyyy-MM-dd"
                                type="date"
                                placeholder="选择结束日期"
                                >
                                </el-date-picker>
                            </el-form-item>
                            <el-form-item>
                                <el-button type="primary" @click="submitForm('ruleForm')">查询</el-button>
                                <el-button @click="resetForm('ruleForm')">重置</el-button>
                            </el-form-item>
                        </el-form>
                    </div>
                </el-card>
            </el-col>
        </el-row>
        <el-row >
            <el-col :span="8" class="card-box" v-for="item in NewChartData">
                <el-card>
                    <div slot="header"><span>{{item.name}}</span></div>
                    <echart-cpn :data="item.option" ></echart-cpn>
                </el-card>
            </el-col>
        </el-row>
    </div>
</template>
<script>
import echartCpn from '@/views/dataChart/chartMenu/cpns/echartCpn.vue'
import {getZzbEchart} from '@/api/dataChart/chartMenu'
import { formatDate } from '../../../../utils'
export default{
   components:{echartCpn},
    data(){
        return{
            //时间限制,符合日期先后顺序的实际情况
            pickerOptionsStart: {
                disabledDate: (time) => {
                let sevenDays = 6 * 24 * 3600 * 1000;  //6天
                if (this.ruleForm.jsrq) {
                    return (
                    time.getTime() > Date.now() - 8.64e6 ||
                    //开始日期要在选择的结束日期之前,大于结束时间的日期不能选
                    time.getTime() > new Date(this.ruleForm.jsrq).getTime() ||
                    //先选结束时间,在结束时间七天之前的不能选(因为包括自身这一天,所以是减去六天)
                    time.getTime() < new Date(this.ruleForm.jsrq).getTime() - sevenDays
                    );
                }
                return time.getTime() > Date.now() - 8.64e6; //今天及之前
                }
            },
            pickerOptionsEnd: {
                disabledDate: (time) => {
                let sevenDays = 6 * 24 * 3600 * 1000;
                if (this.ruleForm.ksrq) {
                    return (
                    time.getTime() > Date.now() - 8.64e6 ||
                    //结束日期要在选择的开始日期之后,小于开始时间的日期不能选
                    time.getTime() < new Date(this.ruleForm.ksrq).getTime() ||
                    //先选开始时间,在开始时间七天之后的不能选(因为包括自身这一天,所以是加上六天)
                    time.getTime() > new Date(this.ruleForm.ksrq).getTime() + sevenDays
                    );
                }
                return time.getTime() > Date.now() - 8.64e6; //今天及之前
                }
            },
            ruleForm: {
                ksrq:'',
                jsrq:''
            },
            NewChartData:{}, //传递给子组件的数据
            rules: {
                ksrq:[{ required: true, message: '请选择开始时间', trigger: 'blur' },],
                jsrq:[{ required: true, message: '请选择结束时间', trigger: 'blur' },]
            }
        }
    },
    watch:{
        NewChartData:{
            deep:true,
            handler(newVal,oldVal){
                console.log(newVal,oldVal,"----------");
            }
        }
    },

    created(){
        this.setDeafaultTimeQuery()
    },
    mounted(){
        //默认查询当前时间前一周的数据
        this.loadEchartData(this.ruleForm)
    },
    methods:{
        //默认开始时间为当前时间的前一周
        setDeafaultTimeQuery() {
            const currentDate = new Date()
            const year = currentDate.getFullYear();
            const month = currentDate.getMonth();
            const date = currentDate.getDate();
            const end = (new Date(year, month, date, 0,0,0)).getTime(); 
            const start = formatDate(end - (3600 * 1000 * 24 * 6)) // 一周前
            this.ruleForm.ksrq= start
            this.ruleForm.jsrq = formatDate(end)
        },
        //点击确定
        submitForm(formName) {
            this.$refs[formName].validate((valid) => {
            if (valid) {
                this.loadEchartData(this.ruleForm)
            } else {
                console.log('error submit!!');
                return false;
            }
            });
        },

        //重置
        resetForm(formName) {
            console.log();
            this.$refs[formName].resetFields();
            this.ruleForm.ksrq = ""
            this.ruleForm.jsrq = ''
        },
        
       //查询事件
        loadEchartData(params){
            this.loading = true;
            console.log('日期',params);
            getZzbEchart(params).then(res=>{
                this.dateCount = res.data[0].count
                this.loading = false;
                this.echartData = res.data
                this.formateEchartData()
            })
        },
       
        formateEchartData(){
                const echartDataObj = {};
                const obj = [];
                const newArr = []
                this.echartData.forEach(val=>{
                    obj.push([val.day,val.qnjrs,val.jrs]);
                    this.$set(echartDataObj,val.item,{
                        name:val.name,
                        option:{
                            dimensions: ['product', '2022', '2023'],
                            source:[]
                        }})
                })
                console.log(obj,"ooooooooooo");
                for(var i=0;i<obj.length;i+=this.dateCount){
                    newArr.push(obj.slice(i,i+this.dateCount));
                }
                console.log(newArr,"aaaaaaa");
                var item = 0;
                for(var key in echartDataObj){
                    //console.log(key, "key");
                    echartDataObj[key].option.source = newArr[item]
                    item++
                } 
                this.NewChartData = echartDataObj
                console.log(this.NewChartData,"重新赋值");
            }
    }

}

</script>
<style scoped>
  .demonstration{
    margin-bottom: 10px;
    font-size: 12px;
    color:#606266;
  }
</style>

大功告成!

转载请注明出处或者链接地址:https://www.qianduange.cn//article/18746.html
标签
评论
发布的文章

jQuery QueryBuilder 教程

2024-10-29 23:10:44

水球图 及各种参数设置

2024-10-29 23:10:13

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!