由于我们在做项目的时候相同的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>
复制
大功告成!