视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
vue之将echart封装为组件
2020-11-27 22:13:33 责编:小采
文档

最近的新项目里,有大量数据图表类的需求,为了增强代码的复用性,减少冗余,我开始思考如何将echart封装为组件调用。本文将会以雷达图为案例,一步步讲解在vue项目中如何使用echart,如何将其封装为能重复调用的组件。

阅读之前,可以先看看我之前的一些文章,这样能更好的理解这次的内容:

【使用vue-cli(vue脚手架)快速搭建项目】://www.gxlcms.com/article/140498.htm

【vue之父子组件间通信实例讲解(props、$ref 、 $emit )】:www.gxlcms.com/article/140581.htm

1. 安装Echarts

首先第一步,肯定是安装Echarts了。通过cd命令进入项目根目录,然后敲以下命令行:

cnpm install echarts -S

安装成功会如下显示,package.json里的dependencies属性也会自动加上Echarts依赖:

安装Echarts

package.json

2.在vue项目中使用Echarts

安装成功以后,我们先要考虑的是如何在vue项目中导入Echarts,并成功初始化一个图表。

下面我会先建两个.vue文件 chart.vue 和 radar-chart.vue 作为这次示例的基础。 chart.vue的角色是调用雷达图,radar-chart.vue的角色是提供雷达图:

//chart.vue 
<template>
 <radar-chart></radar-chart>
</template>

<script>
 import RadarChart from '../components/radar-chart'
 export default {
 name: "chart",
 components: {RadarChart},
 component: RadarChart
 }
</script>
//radar-chart.vue
<template>
</template>
<script>
 export default {
 name: "radar-chart"
 }
</script>

好,正式创建一个Echarts图表了

(1)在radar-chart.vue导入echart :

 // 引入基本模板
 import echarts from 'echarts/lib/echarts'
 // 引入雷达图组件
 import 'echarts/lib/chart/radar'
 // 引入提示框和图例组件
 import 'echarts/lib/component/tooltip'
 import 'echarts/lib/component/legend'

(2)创建图表配置数据,数据格式参考 Echarts官网:

 const option = {
 tooltip: {},
 radar: {
 indicator: [{name: '体育', max: '100'}, {name: '数学', max: '100'}, {name: '化学', max: '100'}, {name: '劳动', max: '100'}, {name: '物理', max: '100'}],
 center: ['50%', '51%']
 },
 series: [{
 type: 'radar',
 itemStyle: {normal: {areaStyle: {type: 'default'}}},
 data: [
 {
 value: [58,56,78,,98],
 name: '各项得分',
 itemStyle: {normal: {color: '#f0ad4e'}}
 }
 ]
 }]
 }

(3)初始化图表:

 const chartObj = echarts.init(document.getElementById('radar'))
 chartObj.setOption(option)

上面几步汇总为以下代码,另外补充一点就是,创建配置数据option和初始化的时候,都要放在mounted钩子函数里执行,这样才能保证获取dom的是时候,dom已完成渲染:

//chart.vue 
<template>
 <radar-chart></radar-chart>
</template>

<script>
 import RadarChart from '../components/radar-chart'
 export default {
 name: "chart",
 components: {RadarChart},
 component: RadarChart
 }
</script>
//radar-chart.vue
<template>
 <div id="radar" class="container"> </div>
</template>

<script>
 // 引入基本模板
 import echarts from 'echarts/lib/echarts'
 // 引入雷达图组件
 import 'echarts/lib/chart/radar'
 // 引入提示框和图例组件
 import 'echarts/lib/component/tooltip'
 import 'echarts/lib/component/legend'
 export default {
 name: "radar-chart",
 mounted(){
 const option = { //创建图表配置数据
 tooltip: {},
 radar: {
 indicator: [{name: '体育', max: '100'}, {name: '数学', max: '100'}, {name: '化学', max: '100'}, {name: '劳动', max: '100'}, {name: '物理', max: '100'}],
 center: ['50%', '51%']
 },
 series: [{
 type: 'radar',
 itemStyle: {normal: {areaStyle: {type: 'default'}}},
 data: [
 {
 value: [58,56,78,,98],
 name: '各项得分',
 itemStyle: {normal: {color: '#f0ad4e'}}
 }
 ]
 }]
 }
 //初始化图表
 const chartObj = echarts.init(document.getElementById('radar'))
 chartObj.setOption(option)
 }
 }
</script>
<style scoped>
 .container{width: 500px;height: 400px;}
</style>

出来的效果是这样的:

效果一

3.将Echarts封装为组件

上面我们已经成功创建一个雷达图了,但是很明显的是,radar-chart.vue里的数据写死的,无法重复调用。接下来着手封装的事情了。

封装的思路是这样的:
(1)chart.vue向radar-chart.vue传递一组个性化数据
(2)radar-chart.vue通过props选项接收数据
(3)提炼接收到的数据,覆盖配置数据option
(4)初始化图表
(如果对如何传递数据不理解,可以先看看我在开始的时候提到的,我的另一篇文章 —— “ vue之父子组件间通信实例讲解(props、$ref 、 $emit )”)

具体代码如下:

//chart.vue (父组件)

<template>
 <radar-chart :items="items"></radar-chart> //传递在子组件prop选项里约定好的数据
</template>

<script>
 import RadarChart from '../components/radar-chart'
 export default {
 name: "chart",
 components: {RadarChart},
 component: RadarChart,
 data () {
 return {
 items: [{name: '体育', value: 95, max: '100'}, {name: '数学', value: 55, max: '100'}, {name: '化学', value: 75, max: '100'}, {name: '劳动', value: 85, max: '100'}, {name: '烹饪', value: 85, max: '100'}]
 }
 }
 }
</script>
//radar-chart.vue (子组件)

<template>
 <div id="radar" class="container"> </div>
</template>

<script>
 // 引入基本模板
 import echarts from 'echarts/lib/echarts'
 // 引入雷达图组件
 import 'echarts/lib/chart/radar'
 // 引入提示框和图例组件
 import 'echarts/lib/component/tooltip'
 import 'echarts/lib/component/legend'
 export default {
 name: "radar-chart",
 props: { //接受父组件传递来的数据
 items: {
 type: Array,
 default () { //默认数据,没有数剧的情况下启用
 return [{name: '生物', value: 95, max: '100'}, {name: '数学', value: 55, max: '100'}, {name: '语文', value: 86, max: '100'}, {name: '物理', value: 54, max: '100'}, {name: '美术', value: 59, max: '100'}]
 }
 },
 },
 mounted(){
 let values = [] //提炼接收到的数据
 this.items.forEach(el => {
 values.push(el.value) 
 }) 
 const option = { //覆盖配置数据option
 tooltip: {},
 radar: {
 indicator: this.items, 
 center: ['50%', '51%']
 },
 series: [{
 type: 'radar',
 itemStyle: {normal: {areaStyle: {type: 'default'}}},
 data: [
 {
 value: values, 
 name: '各项得分',
 itemStyle: {normal: {color: '#f0ad4e'}}
 }
 ]
 }]
 }
 //初始化
 const chartObj = echarts.init(document.getElementById('radar'))
 chartObj.setOption(option)
 }
 }
</script>
<style scoped>
 .container{width: 500px;height: 400px;}
</style>

封装以后,就能传递自定义的数据,反复调用了。上面代码最后的效果是这样的:

效果二

4.细节优化

基本的功能已经实现了,下面我们来优化下一些细节。

不知道大家有没发现radar-chart.vue里的<template>-id是写死的,这会出现什么问题?当一个页面调用两次这个雷达图组件,id就会重复了,从而报错。

为了解决这个问题,我引入了uuid(vue-cli项目自带,不需另外安装),意在为每个生成的雷达图配一个不重复的随机id。还需要注意的是,我们要在created()方法里去做这个生成id的事情,如果写在mounted了就会出现无法初始化的情况,因为来不及渲染新的ID,就执行document.getElementById()了,具体代码如下:

<template>
 <div>
 <radar-chart :items="items_one"></radar-chart>
 <radar-chart :items="items_two"></radar-chart>
 </div>
</template>

<script>
 import RadarChart from '../components/radar-chart'
 export default {
 name: "chart",
 components: {RadarChart},
 component: RadarChart,
 data () {
 return {
 items_one: [{name: '体育', value: 95, max: '100'}, {name: '数学', value: 55, max: '100'}, {name: '化学', value: 75, max: '100'}, {name: '劳动', value: 85, max: '100'}, {name: '烹饪', value: 85, max: '100'}],
 items_two: [{name: '体育', value: 22, max: '100'}, {name: '数学', value: 55, max: '100'}, {name: '化学', value: 75, max: '100'}, {name: '劳动', value: 85, max: '100'}, {name: '烹饪', value: 85, max: '100'}]
 }
 }
 }
</script>
<template>
 <div :id="elId" class="container"> </div>
</template>

<script>
 // 引入基本模板
 import echarts from 'echarts/lib/echarts'
 // 引入雷达图组件
 import 'echarts/lib/chart/radar'
 // 引入提示框和图例组件
 import 'echarts/lib/component/tooltip'
 import 'echarts/lib/component/legend'
 //引入uuid文件
 import uuidv1 from 'uuid/v1' 
 export default {
 name: "radar-chart",
 props: {
 items: {
 type: Array,
 default () {
 return [{name: '生物', value: 95, max: '100'}, {name: '数学', value: 55, max: '100'}, {name: '语文', value: 86, max: '100'}, {name: '物理', value: 54, max: '100'}, {name: '美术', value: 59, max: '100'}]
 }
 },
 },
 data () {
 return {
 elId: ''
 }
 },
 created(){
 this.elId = uuidv1() //获取随机id
 },
 mounted(){
 let values = []
 this.items.forEach(el => {
 values.push(el.value)
 })
 const option = {
 tooltip: {},
 radar: {
 indicator: this.items,
 center: ['50%', '51%']
 },
 series: [{
 type: 'radar',
 itemStyle: {normal: {areaStyle: {type: 'default'}}},
 data: [
 {
 value: values,
 name: '各项得分',
 itemStyle: {normal: {color: '#f0ad4e'}}
 }
 ]
 }]
 }
 const chartObj = echarts.init(document.getElementById(this.elId));
 chartObj.setOption(option)
 }
 }
</script>
<style scoped>
 .container{width: 500px;height: 400px;}
</style>

成功解决重复id的问题:

效果三

整个封装echart的思路就是上面那样了,其实这个demo还不完美,像雷达图的宽高也是写死的,还没来得及做更多的优化,后面有空慢慢再完善它~

下载本文
显示全文
专题