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