Echarts在Vue2中的封装(可以直接cv套用~)
在这里做一个适用于饼图、折线图、柱状图的简单封装,其他配置项按项目需求自行添加或改造即可。
(效果图在最后)
1.封装echarts组件
1.引入echarts(跳转自行查看)这里省去安装与main.js引入部分
<template>
<!-- 绑定容器 -->
<div ref="echart"></div>
</template>
<script>
import * as echart from "echarts";
</script>
2.配置echarts接收的数据,因为常用的图表有饼图、折线图、柱状图等,所以这里只做有轴、无轴表的区分
export default {
props: {
//是否为有轴图表
isAxisChart: {
type: Boolean,
default: true,
},
//图表数据
chartData: {
type: Object,
default() {
return {};
},
},
},
//监听图表数据变化
watch: {
chartData: {
handler: function () {
this.initChart();
},
deep: true,
},
},
}
3.对图表的选项进行配置,这里仅配置了一些常用选项(字体颜色、提示框、XY轴、图表类型等)
data() {
return {
//有轴表配置项
axisOptions: {
legend: {
//字体颜色
textStyle: {
color: "#333",
},
},
//grid组件离容器左侧的距离
grid: {
left: "20%",
},
//提示框触发规则
tooltip: {
trigger: "item",
},
//X轴配置
xAxis: {
type: "category",
data: [],
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
axisLabel: {
interval: 0, //X轴间隔
color: "#17b3a3",
},
},
//Y轴配置
yAxis: [
{
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
},
],
//颜色配置
color: [
"#2ec7c9",
"#b6a2de",
"#5ab1ef",
"#ffb980",
"#d87a80",
"#8d98b3",
],
//图表类型与数据
series: [],
},
//无轴表配置项
normalOptions: {
//提示框触发规则
tooltip: {
trigger: "item",
},
//颜色配置
color: [
"#0f78f4",
"#dd536b",
"#9462e5",
"#a6a6a6",
"#e1bb22",
"#39c362",
"#3ed1cf",
],
//图表类型与数据
series: [],
},
};
},
4.根据父组件需要的图表类型对props中的数据进行分发
methods: {
//根据图表类型配置图表项
initChart() {
this.initChartData();
if (this.echart) {
this.echart.setOption(this.options);
} else {
this.echart = echart.init(this.$refs.echart);
this.echart.setOption(this.options);
}
},
//根据图表类型导入图表数据
initChartData() {
if (this.isAxisChart) {
//设置X轴
this.axisOptions.xAxis.data = this.chartData.xData;
//设置图表类型
this.axisOptions.series = this.chartData.series;
} else {
//无轴表
this.normalOptions.series = this.chartData.series;
}
},
},
computed: {
options() {
return this.isAxisChart ? this.axisOptions : this.normalOptions;
},
},
5.对上面三步骤进行的整合,该部分可直接CV拿去创建自己的图表封装组件
<template>
<!-- 绑定容器 -->
<div ref="echart"></div>
</template>
<script>
import * as echart from "echarts";
export default {
props: {
//是否为有轴图表
isAxisChart: {
type: Boolean,
default: true,
},
//图表数据
chartData: {
type: Object,
default() {
return {};
},
},
},
//监听图表数据变化
watch: {
chartData: {
handler: function () {
this.initChart();
},
deep: true,
},
},
methods: {
//根据图表类型配置图表项
initChart() {
this.initChartData();
if (this.echart) {
this.echart.setOption(this.options);
} else {
this.echart = echart.init(this.$refs.echart);
this.echart.setOption(this.options);
}
},
//根据图表类型导入图表数据
initChartData() {
if (this.isAxisChart) {
//设置X轴
this.axisOptions.xAxis.data = this.chartData.xData;
//设置图表类型
this.axisOptions.series = this.chartData.series;
} else {
//无轴表
this.normalOptions.series = this.chartData.series;
}
},
},
computed: {
//判断图表类型
options() {
return this.isAxisChart ? this.axisOptions : this.normalOptions;
},
},
data() {
return {
//有轴表配置项
axisOptions: {
legend: {
//字体颜色
textStyle: {
color: "#333",
},
},
//grid组件离容器左侧的距离
grid: {
left: "20%",
},
//提示框触发规则
tooltip: {
trigger: "item",
},
//X轴配置
xAxis: {
type: "category",
data: [],
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
axisLabel: {
interval: 0, //X轴间隔
color: "#17b3a3",
},
},
//Y轴配置
yAxis: [
{
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
},
],
//颜色配置
color: [
"#2ec7c9",
"#b6a2de",
"#5ab1ef",
"#ffb980",
"#d87a80",
"#8d98b3",
],
//图表类型
series: [],
},
//无轴表配置项
normalOptions: {
//提示框触发规则
tooltip: {
trigger: "item",
},
//颜色配置
color: [
"#0f78f4",
"#dd536b",
"#9462e5",
"#a6a6a6",
"#e1bb22",
"#39c362",
"#3ed1cf",
],
//图表类型
series: [],
},
};
},
};
</script>
2.在页面中使用组件
在这里整合了三种图(饼图、折线图、柱状图),需要固定父组件图表数据的数据对象属性以适配该组件(见注释图表数据),且重点在图表数据配置项series、xData数据处理部分,每种图表对其数据的处理方式各有不同,具体看mounted里的处理方式(现实开发中以后端返回的数据结构为准)
<template>
<el-row>
<el-col :span="12">
<el-card shadow="hover" class="middle">
<!-- 饼图 -->
<EchartsView
:chartData="pieData"
style="height: 700px"
:isAxisChart="false"
/>
</el-card>
</el-col>
<el-col :span="11" style="margin-left: 20px; margin-top: 20px">
<el-card shadow="hover">
<!-- 折线图 -->
<EchartsView :chartData="lineData" style="height: 375px" />
</el-card>
<el-card shadow="hover">
<!-- 柱状图 -->
<EchartsView :chartData="barData" style="height: 375px" />
</el-card>
</el-col>
</el-row>
</template>
<script>
import EchartsView from "@/components/MAG_echarts.vue";
import MockData from "./mock.json";
export default {
components: {
EchartsView,
},
data() {
return {
//图表数据(接取数据适配组件)
lineData: { xData: [], series: [] },
barData: { xData: [], series: [] },
pieData: { series: [] },
};
},
mounted() {
//模拟从后端接取数据
let data = MockData;
//饼图
this.pieData.series = [
{
//获取的数据
data: data.pieData,
//饼图类型
type: "pie",
},
];
//折线
const keyArray = Object.keys(data.lineData.data[0]); //遍历取出数据名称
const series = [];
keyArray.forEach((key) => {
series.push({
name: key, //数据名称
data: data.lineData.data.map((item) => item[key]), //取值
type: "line", //折线类型
});
});
this.lineData.xData = data.lineData.date; //X轴数据
this.lineData.series = series;
//柱状图
this.barData.xData = data.barData.map((item) => item.date); //X轴数据
this.barData.series = [
{
name: "新增用户", //柱列名
data: data.barData.map((item) => item.new), //对应数据
type: "bar", //柱状类型
},
{
name: "活跃用户", //柱列名
data: data.barData.map((item) => item.active), //对应数据
type: "bar",
},
];
},
};
</script>
最后附上模拟数据(json格式文件)以方便实践
{
"pieData": [
{
"name": "小米",
"value": 2999
},
{
"name": "苹果",
"value": 5999
},
{
"name": "vivo",
"value": 1500
},
{
"name": "魅族",
"value": 2599
},
{
"name": "oppo",
"value": 2200
},
{
"name": "三星",
"value": 4399
}
],
"barData": [
{
"date": "周一",
"new": 5,
"active": 200
},
{
"date": "周二",
"new": 10,
"active": 500
},
{
"date": "周三",
"new": 12,
"active": 550
},
{
"date": "周四",
"new": 60,
"active": 800
},
{
"date": "周五",
"new": 70,
"active": 850
},
{
"date": "周六",
"new": 73,
"active": 900
},
{
"date": "周天",
"new": 5,
"active": 200
}
],
"lineData": {
"date": ["1", "2", "3", "4", "5", "6", "7"],
"data": [
{
"苹果": 5449,
"vivo": 386,
"oppo": 7259,
"魅族": 2162,
"三星": 787,
"小米": 2989
},
{
"苹果": 1631,
"vivo": 4883,
"oppo": 1938,
"魅族": 1580,
"三星": 3186,
"小米": 2900
},
{
"苹果": 6449,
"vivo": 3665,
"oppo": 1336,
"魅族": 6206,
"三星": 6746,
"小米": 1714
},
{
"苹果": 1753,
"vivo": 3342,
"oppo": 560,
"魅族": 1976,
"三星": 2260,
"小米": 4177
},
{
"苹果": 3024,
"vivo": 3362,
"oppo": 1425,
"魅族": 731,
"三星": 7170,
"小米": 2777
},
{
"苹果": 2686,
"vivo": 7326,
"oppo": 1936,
"魅族": 6962,
"三星": 1338,
"小米": 7573
},
{
"苹果": 2445,
"vivo": 3797,
"oppo": 2455,
"魅族": 1409,
"三星": 5121,
"小米": 3048
}
]
}
}