子组件
<!-- 自定义 echart 组件 -->
<template>
<div>
<!-- echart表格 -->
<div :id="myChartId" :style="echartStyle"></div>
<Spin size="large" fix v-if="isLoadding"></Spin>
</div>
</template>
<script>
import echarts from "echarts";
export default {
props: {
// ID
myChartId: {
type: String,
default: "myChartBarId"
},
// 样式
echartStyle: {
type: String,
default: ""
},
// 标题文本
titleText: {
type: String,
default: ""
},
// 标题文本
subText: {
type: String,
default: ""
},
//是否包含坐标轴的刻度标签
containLabel: {
type: Boolean,
default: false
},
// 条形图数据
opinionData: {
type: Object,
default() {
return {};
}
},
//条形图颜色
barColor: {
type: String,
default: ""
},
},
data() {
return {
isLoadding:true
};
},
watch: {
opinionData(val, oldval) {
this.$nextTick(function() {
this.isLoadding=false;
this.drawPie(this.myChartId);
});
}
},
methods: {
// 监听扇形图点击
eConsole(param) {
// 向父组件传值
this.$emit("echarEvent", param);
}, // 绘制饼状图
drawPie(id) {
this.charts = echarts.init(document.getElementById(id));
this.charts.on("click", this.eConsole);
this.charts.setOption({
title: {
text: this.titleText, // 标题文本
subtext: this.subText, //副标题文本
x: '55%',//文字距离左边大小
textAlign: 'center'
},
tooltip: {
// trigger: 'item',
// formatter: "{a} <br/>{b}: {c} ({d}%)"//模板变量有 {a}、{b}、{c}、{d},分别表示系列名,数据名,数据值,百分比。
},
grid: [{
top: 50,//组件离容器上侧的距离。
left: 10,//组件离容器左侧的距离。
containLabel: this.containLabel//是否包含坐标轴的刻度标签。
}],
xAxis: [{
type: 'value',//数值轴类型
splitLine: {//是否显示轴线
show: false
}
}],
yAxis: [{
type: 'category',
data: Object.keys(this.opinionData),//条形图y轴标签数据
axisLabel: {
interval: 0,//坐标轴刻度标签的显示间隔,设置成 0 强制显示所有标签
rotate: 30//y轴标签旋转角度
},
splitLine: {//是否显示轴线
show: false
}
}],
series: [
{
type: 'bar',//数据条
stack: 'chart',//堆叠
z: 3,
label: {
normal: {
position: 'right',
show: true,
}
},
itemStyle: {
normal: {
color: this.barColor
}
},
data: this.changeOpinionData(this.opinionData)
},
{
type: 'bar',//背景条
stack: 'chart',//堆叠
silent: true,
itemStyle: {
normal: {
color: '#EEEEEE'
}
},
data: this.getRest(this.opinionData)
}
],
});
},
changeOpinionData(ary){//取条形数据值
var newAry=Object.keys(ary).map(function (key) {
return ary[key];
})
return newAry;
},
getTotol(ary){//统计总数
var totol=Object.keys(ary).reduce(function (all, key) {
return all + ary[key];
}, 0)
return totol;
},
getRest(ary){//统计余量
var that=this;
var rest=Object.keys(ary).map(function (key) {
return that.getTotol(ary) - ary[key];
})
return rest;
}
}
};
</script>
父组件引用示例
<style lang="less">
@import "./home.less";
@import "../../styles/common.less";
</style>
<template>
<Row>
<Col span="8">
<draw-bar
:myChartId="'mychart4'"
:echartStyle="'width:450px;height:300px;margin:auto'"
:titleText="drawPieInfo.titleText"
:subText="drawPieInfo.subText"
:containLabel="drawPieInfo.containLabel"
:barColor="drawPieInfo.barColor"
:opinionData="drawPieInfo.opinionData"
@echarEvent="echarEvent($event,'案由统计')"
></draw-bar>
</Col>
</Row>
</template>
<script>
import drawBar from "@/components/zhEchart/drawBar.vue";
import {
countLawCase
} from '@/api/homeDate';
export default {
name: 'home',
components: {
drawBar
},
data () {
return {
drawPieInfo: {
titleText: "案由统计",
subText: "总计",
containLabel: true,
barColor: "#3FB1E3",
opinionData: {} //条形数据
},
lawCaseCount:[],//案件状态
};
},
mounted () {
this.initChart();
},
methods: {
initChart(){//初始化chart数据
countLawCase().then(res=>{
if(res.data.state==100){
let data=res.data.data;
this.lawCaseCount=data.lawCaseCount;
var that=this;
var ary=Object.keys(this.lawCaseCount).map(function (key) {
return {
name: key,
value: that.lawCaseCount[key]//获取条形数据
}
});
this.drawPieInfo.opinionData=ary;//设置条形数据
this.drawPieInfo.subText = "总计:" + this.getTotol(this.lawCaseCount); //设置总数
}else{
this.$Message.error(res.data.message);
}
});
},
echarEvent(){
},
getTotol(ary) {
//统计总数
var totol = Object.keys(ary).reduce(function(all, key) {
return all + ary[key];
}, 0);
return totol;
},
},
};
</script>
值得注意的是:由于echart数据依赖DOM更新,再次赋值时需要重新初始化echart,在父组件异步获取数据传入子组件时,要用watch监听传入的值并重新进行DOM渲染,数据更新了但视图并没有及时更新因此就需要$nextTick进行DOM监听来重新初始化echart