一、环境介绍
工欲善其事必先利其器,所以先介绍环境和依赖,让你少吃版本的亏。
环境
- vue版本 2.6+
- echarts版本 4.2.1 依赖安装:
- npm install echarts resize-detector lodash -S
二、如何一步步的进行封装
- 我们首先得有一个echarts实例吧,先通过init()方法初始化;既然是公共组件,那么在组件中我们不需要关心业务,所以把option采用动态传入的方式;一个页面多处使用echarts,id相同,感觉不太舒服的样子,id也动态传入吧
<template>
<div :ref="id" />
</template>
<script>
import echarts from 'echarts'
export default {
props: {
// 动态option
option: {
type: Object,
default: () => {}
},
// id,赋予一个默认值,那么我们不传id也是可以的
id: {
type: String,
default: 'chartDom'
}
},
data() {
return {
}
},
mounted() {
this.renderCharts()
},
methods: {
// 初始化echarts
renderCharts() {
this.chart = echarts.init(this.$refs[this.id])
if (this.option) {
this.chart.setOption(this.option)
}
}
}
}
</script>
- 到这里,我们组件其实就已经可以使用了,基本的轮廓有了,下面继续添枝加叶。当我们缩放屏幕的时候,这时的图表可不会自动缩放啥的。好的,不卖关子了,当容器大小改变时,应该去调用resize()函数,改变图表尺寸,屏幕缩放,防抖节流得考虑吧,为了省事,直接用loadsh吧。
// 监听元素大小(尺寸)变化
import { addListener, removeListener } from 'resize-detector'
// 防抖
import debounce from 'lodash/debounce'
created() {
this.resizefn = debounce(this.resize, 300)
},
mounted() {
this.renderCharts()
// 新增,监听元素尺寸变化
addListener(this.$refs[this.id], this.resizefn)
},
methods: {
// resize()函数
resize() {
this.chart.resize()
}
}
- 下面来进行优化,比如在beforeDestroy中移除监听器,销毁echarts实例等;当然我们还需要监听option,当option变化时,重新setOption()
watch: {
option: {
handler(val) {
this.chart.setOption(this.option)
},
deep: true
}
},
beforeDestroy() {
// 移除监听器
removeListener(this.$refs[this.id], this.resizefn)
// 销毁echarts实例
this.chart.dispose()
this.chart = null
},
methods: {
renderCharts() {
this.chart = echarts.init(this.$refs[this.id])
if (this.option) {
this.chart.setOption(this.option)
}
const _this = this
// 注册点击事件
this.chart.on('click', function(params) {
_this.$emit('onClick', params)
})
}
}
三、完整代码及使用
完整代码
<template>
<div :ref="id" />
</template>
<script>
import echarts from 'echarts'
// 监听元素大小(尺寸)变化
import { addListener, removeListener } from 'resize-detector'
// 防抖
import debounce from 'lodash/debounce'
export default {
props: {
option: {
type: Object,
default: () => {}
},
id: {
type: String,
default: 'chartDom'
}
},
data() {
return {
}
},
watch: {
option: {
handler(val) {
this.chart.setOption(this.option)
},
deep: true
}
},
created() {
// 防抖,性能优化
this.resizefn = debounce(this.resize, 300)
},
mounted() {
this.renderCharts()
// 监听元素尺寸变化
addListener(this.$refs[this.id], this.resizefn)
},
beforeDestroy() {
// 移除监听器
removeListener(this.$refs[this.id], this.resizefn)
// 销毁echarts实例
this.chart.dispose()
this.chart = null
},
methods: {
resize() {
this.chart.resize()
},
// 初始化
renderCharts() {
this.chart = echarts.init(this.$refs[this.id])
if (this.option) {
this.chart.setOption(this.option)
}
const _this = this
// 注册点击事件
this.chart.on('click', function(params) {
_this.$emit('onClick', params)
})
}
}
}
</script>
使用
<template>
<div>
<h5 style="text-align:center;">echarts图表的封装</h5>
<Charts v-if="chartOption" :option="chartOption" style="height:600px;"></Charts>
</div>
</template>
<script>
import Charts from './components/Charts'
export default {
components: {
Charts
},
data() {
return {
chartOption: null
}
},
created() {
this.getChartsData()
},
methods: {
getChartsData() {
setTimeout(() => {
this.chartOption = {
title: {
text: '疯狂测试'
},
tooltip: {
trigger: 'item'
},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [{
name: '销量',
type: 'pie',
data: [100, 150, 50, 200, 120, 300]
}]
}
}, 1000)
}
}
}
</script>