VUE中使用Echarts图表
最近在重构公司的系统后台,项目采用的是前后端分离模式,我负责的数据统计接口和前端模块的开发。上周出了数据统计的接口,这周的话,再写前端,前端主要就是用图表展示各种的统计信息,所以选择了echarts进行可视化开发。这里提下Echarts,大学的时候接触的比较多,感觉Echarts的扩展性比较强,自定义样式的话也提供配置项,当时网上的教程比较少,想要一些炫酷的效果也只能自己按照文档一点点尝试,其实按
更新:在VUE中封装图表时,你应该会遇到下面两个问题,到时候可以看下这里的解决方案:
最近在重构公司的系统后台,项目采用的是前后端分离模式,我负责的数据统计接口和前端模块的开发。上周出了数据统计的接口,这周的话,再写前端,前端主要就是用图表展示各种的统计信息,所以选择了echarts进行可视化开发。
这里提下Echarts,大学的时候接触的比较多,感觉Echarts的扩展性比较强,自定义样式的话也提供配置项,当时网上的教程比较少,想要一些炫酷的效果也只能自己按照文档一点点尝试,其实按照官方文档操作的话,修改起来也比较方便。
因为项目需要用到图表的地方比较多,所以对echarts图表简单的封装了下,下面是开发流程:
一:npm命令安装Echarts
在项目的根目录终端运行下列命令
npm install echarts --save
node_modules文件夹中存在echarts则代表安装成功
二:vue项目中引用echarts
在main.js使用import引入echarts
// 引入echarts
import * as echarts from 'echarts'
// 设置全局变量
Vue.prototype.$echarts = echarts
三:echarts子组件开发
先封装了一个基础折线图,首先在components新建Chart文件夹存放二次封装的组件,然后新建ChartBasicLine.vue文件
其实vue中使用Echarts和原生的调用流程几乎一致,现在模板里面写下面标签代码
<div class="chart_content">
<div
:ref="chartObj.type"
class="chart_show"
/>
</div>
这里的ref很重要,用来获取本页面的dom元素,也就是当前的图表元素,在js图表初始化需要用到这个
然后在js的props可以引用父元素的数据,该数据是对象类型,用来传递父组件的图表信息,如:图片类型、X轴数据、Y轴数据等信息
export default {
name: 'ChartBasicLine',
props: {
chartObj: {
type: Object
}
}
}
接着在js中定义变量图表的配置信息option,这里的话,x和y轴的数据不用定义,是父组件传渲染的。
// 图表配置信息
option: {
tooltip: {
trigger: 'axis'
},
grid: {
top: '22px',
left: '40px',
right: '30px'
},
xAxis: {
type: 'category'
},
yAxis: {
type: 'value'
},
series: [{
type: 'line'
}]
}
不同的图表option的值是不同的,需要去Echarts官网示例中查看代码
最后是初始化和渲染图表,这里定义showChart方法,在mounted中调用,其中初始化中refs代表一个对象,持有已注册过的ref的所有子组件,根据类型,渲染不同位置的图表
export default {
name: 'ChartBasicLine',
props: {
chartObj: {
type: Object
}
},
data() {
return {
option: {
tooltip: {
trigger: 'axis'
},
grid: {
top: '22px',
left: '40px',
right: '30px'
},
xAxis: {
type: 'category'
},
yAxis: {
type: 'value'
},
series: [{
type: 'line'
}]
}
}
},
mounted() {
// 初始化图表信息
this.showChart()
},
methods: {
showChart() {
this.option.xAxis['data'] = this.chartObj.xData
this.option.series[0]['data'] = this.chartObj.yData
const myChart = this.$echarts.init(this.$refs[this.chartObj.type])
myChart.setOption(this.option)
}
}
}
如上所示就是子组件的开发流程
如果想在单页面引用的话,上面div的ref去除:,定义一个值,showChart中设置下X和Y轴的数据就可
四:父组件调用子组件
这里的话就比较简单了,就是调用子组件就行,在index.vue中js引入子组件,定义组件所需要的变量值
// 引入图表子组件
import ChartBasicLine from '@/components/Chart/ChartBasicLine'
export default {
components: {
ChartBasicLine
},
data() {
return {
chartRegUser: {
num: 100,
percent: '0.00%',
status: 0,
type: 'reg_user',
tips: '新增用户',
title: '新增用户(NU)',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
},
chartActiveUser: {
num: 100,
percent: '0.00%',
status: 0,
type: 'active_user',
tips: '活跃用户',
title: '活跃用户(AU)',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
},
chartPaidUser: {
num: 100,
percent: '0.00%',
status: 0,
type: 'paid_user',
tips: '付费用户',
title: '新增用户(PU)',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
},
chartPaidMoney: {
num: 100,
percent: '0.00%',
status: 0,
type: 'paid_money',
tips: '付费金额',
title: '付费金额',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
}
}
}
}
然后在模板中调用下就行:
<ChartBasicLine :chartObj="chartRegUser" />
<ChartBasicLine :chartObj ="chartActiveUser" />
<ChartBasicLine :chartObj="chartPaidUser" />
<ChartBasicLine :chartObj="chartPaidMoney" />
五:效果展示
六:父组件及子组件源码
父组件
<template>
<div class="index">
<div class="index_top">
<div class="index_top_title">
首页
</div>
<div class="index_top_select">
<el-select v-model="value" placeholder="请选择" size="medium">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<ChartBasicLine :chartObj="chartRegUser" />
<ChartBasicLine :chartObj ="chartActiveUser" />
<ChartBasicLine :chartObj="chartPaidUser" />
<ChartBasicLine :chartObj="chartPaidMoney" />
</div>
</template>
<script>
import ChartBasicLine from '@/components/Chart/ChartBasicLine'
export default {
components: { ChartBasicLine },
data() {
return {
options: [{
value: '',
label: '全部'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}],
value: '',
chartRegUser: {
num: 100,
percent: '0.00%',
status: 0,
type: 'reg_user',
tips: '新增用户',
title: '新增用户(NU)',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
},
chartActiveUser: {
num: 100,
percent: '0.00%',
status: 0,
type: 'active_user',
tips: '活跃用户',
title: '活跃用户(AU)',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
},
chartPaidUser: {
num: 100,
percent: '0.00%',
status: 0,
type: 'paid_user',
tips: '付费用户',
title: '新增用户(PU)',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
},
chartPaidMoney: {
num: 100,
percent: '0.00%',
status: 0,
type: 'paid_money',
tips: '付费金额',
title: '付费金额',
xData: ['2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01', '2021-08-01'],
yData: [150, 230, 224, 218, 135, 147, 260]
}
}
}
}
</script>
<style lang='scss' scoped>
.index {
width: 100%;
.index_top {
width: 97%;
height: 60px;
line-height: 60px;
margin: 10px 1.5%;
display: flex;
justify-content: space-between;
.index_top_title {
font-size: 20px;
font-weight: bold;
color: #333333;
}
}
}
</style>
子组件
<template>
<div class="ChartBasicLine">
<div class="chart_box">
<div class="chart_top">
<div class="chart_top_title">
{{chartObj.title}}
</div>
<div class="chart_top_link">
查看详情
</div>
</div>
<div class="chart_info">
<div class="chart_info_left">
今日
<span class="chart_today">{{chartObj.num}}</span>
较昨日:
<span>{{chartObj.percent}}</span>
</div>
<div class="chart_info_time">
<div>
时间筛选:
</div>
<div>
<el-select v-model="value" placeholder="请选择" size="medium">
<el-option
v-for="item in dateArr"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
</div>
<div class="chart_content">
<div
:ref="chartObj.type"
class="chart_show"
/>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ChartBasicLine',
props: {
showTitle: {
type: Boolean,
default: false
},
title: {
type: String,
default: null
},
chartObj: {
type: Object
}
},
data() {
return {
dateArr: [{
value: '0',
label: '实时'
}, {
value: '1',
label: '自然日'
}, {
value: '2',
label: '自然周'
}, {
value: '3',
label: '自然月'
}],
value: '',
option: {
tooltip: {
trigger: 'axis'
},
grid: {
top: '22px',
left: '40px',
right: '30px'
},
xAxis: {
type: 'category'
},
yAxis: {
type: 'value'
},
series: [{
type: 'line'
}]
}
}
},
mounted() {
this.showChart()
},
methods: {
showChart() {
this.option.xAxis['data'] = this.chartObj.xData
this.option.series[0]['data'] = this.chartObj.yData
const myChart = this.$echarts.init(this.$refs[this.chartObj.type])
myChart.setOption(this.option)
}
}
}
</script>
<style>
.el-input {
margin-right: 0 !important;
}
</style>
<style scoped>
.chart_box {
width: 47%;
height: 500px;
margin: 0px 1.5% 40px;
padding: 0 1.5%;
background-color: #ffffff;
border-radius: 4px;
box-shadow: 0 5px 5px 0 rgb(51 51 51 / 5%);
float: left;
}
.chart_top {
width: 100%;
height: 40px;
padding: 10px 0;
line-height: 40px;
font-size: 18px;
font-weight: bold;
display: flex;
justify-content: space-between;
}
.chart_top_link {
font-size: 14px;
color: #2F54EB;
font-weight: unset !important;
}
.chart_info {
width: 100%;
height: 40px;
line-height: 40px;
margin-top: 10px;
display: flex;
justify-content: space-between;
}
.chart_info_left {
font-size: 15px;
}
.chart_info_time div {
display: inline-block;
vertical-align: top;
}
.chart_today {
font-size: 25px;
font-weight: bold;
color: #2F54EB;
margin: 0 20px 0 5px;
}
.chart_content {
width: 100%;
height: 380px;
margin-top: 10px;
}
.chart_show {
width: 100%;
height: 350px;
zoom: 1.25
}
</style>
更多推荐
所有评论(0)