vue之将echart封装为组件


Posted in Javascript onJune 02, 2018

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

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

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

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

1. 安装Echarts

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

cnpm install echarts -S

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

vue之将echart封装为组件

安装Echarts

vue之将echart封装为组件

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,64,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,64,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>

出来的效果是这样的:

vue之将echart封装为组件

效果一

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>

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

vue之将echart封装为组件

效果二

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的问题:

vue之将echart封装为组件

效果三

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
5款Javascript颜色选择器
Oct 25 Javascript
jQuery Tab插件 用于在Tab中显示iframe,附源码和详细说明
Jun 27 Javascript
JavaScript高级程序设计(第3版)学习笔记7 js函数(上)
Oct 11 Javascript
解决javascript:window.close()在chrome,Firefox下失效的问题
May 07 Javascript
javascript弹出窗口实现代码
Nov 12 Javascript
javascript实现的网站访问量统计代码
Dec 20 Javascript
微信小程序 解析网页内容详解及实例
Feb 22 Javascript
angular过滤器实现排序功能
Jun 27 Javascript
electron demo项目npm install安装失败的解决方法
Feb 06 Javascript
基于Axios 常用的请求方法别名(详解)
Mar 13 Javascript
Node.js Express安装与使用教程
May 11 Javascript
vue router动态路由设置参数可选问题
Aug 21 Javascript
React学习笔记之高阶组件应用
Jun 02 #Javascript
浅谈node中的cluster集群
Jun 02 #Javascript
详解AngularJS 过滤器的使用
Jun 02 #Javascript
简化vuex的状态管理方案的方法
Jun 02 #Javascript
深入了解javascript 数组的sort方法
Jun 01 #Javascript
js 数组详细操作方法及解析合集
Jun 01 #Javascript
vue 中动态绑定class 和 style的方法代码详解
Jun 01 #Javascript
You might like
php 过滤危险html代码
2009/06/29 PHP
php文本转图片自动换行的方法
2013/03/13 PHP
深入HTTP响应状态码速查表的详解
2013/06/07 PHP
PHP借助phpmailer发送邮件
2015/05/11 PHP
PHP序列化操作方法分析
2016/09/28 PHP
Laravel框架自定义公共函数的引入操作示例
2019/04/16 PHP
PHP连接MySQL数据库操作代码实例解析
2020/07/11 PHP
ext jquery 简单比较
2010/04/07 Javascript
Jquery增加鼠标中间功能mousewheel的实例代码
2013/09/05 Javascript
js判断两个日期是否相等的方法
2013/09/10 Javascript
JavaScript学习笔记之内置对象
2015/01/22 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
2016/12/18 Javascript
BootStrap 导航条实例代码
2017/05/18 Javascript
Vue 应用中结合vux使用微信 jssdk的方法
2018/08/28 Javascript
详解用场景去理解函数柯里化(入门篇)
2019/04/11 Javascript
微信小程序授权登录解决方案的代码实例(含未通过授权解决方案)
2019/05/10 Javascript
Node.js创建一个Express服务的方法详解
2020/01/06 Javascript
javascript绘制简单钟表效果
2020/04/07 Javascript
react PropTypes校验传递的值操作示例
2020/04/28 Javascript
浅谈JavaScript 声明提升
2020/09/14 Javascript
vue+Element-ui实现分页效果
2020/11/15 Javascript
[01:41]DOTA2超级联赛专访YYF 称一辈子难忘TI2
2013/05/28 DOTA
python基础教程之缩进介绍
2014/08/29 Python
Python提示[Errno 32]Broken pipe导致线程crash错误解决方法
2014/11/19 Python
TensorFlow模型保存和提取的方法
2018/03/08 Python
Python实现求两个数组交集的方法示例
2019/02/23 Python
PHP统计代码行数的小代码
2019/09/19 Python
Python 取numpy数组的某几行某几列方法
2019/10/24 Python
python读取图片的几种方式及图像宽和高的存储顺序
2020/02/11 Python
松本清官方海外旗舰店:日本最大的药妆连锁店
2017/11/21 全球购物
经济职业学院毕业生自荐书
2014/03/17 职场文书
大学生见习期满自我鉴定
2014/09/13 职场文书
惊涛骇浪观后感
2015/06/05 职场文书
Python Django模型详解
2021/10/05 Python
vue打包时去掉所有的console.log
2022/04/10 Vue.js
Mysql索引失效 数据库表中有索引还是查询很慢
2022/05/15 MySQL