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 相关文章推荐
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
Feb 23 Javascript
javascript判断是否按回车键并解决浏览器之间的差异
May 13 Javascript
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
Nov 23 Javascript
JavaScript常用字符串与数组扩展函数小结
Apr 24 Javascript
bootstrap laydate日期组件使用详解
Jan 04 Javascript
详解vue2路由vue-router配置(懒加载)
Apr 08 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
Jul 21 Javascript
JS 中可以提升幸福度的小技巧(可以识别更多另类写法)
Jul 28 Javascript
swiper在vue项目中loop循环轮播失效的解决方法
Sep 15 Javascript
jquery实现二级导航下拉菜单效果实例
May 14 jQuery
javascript自定义日期比较函数用法示例
Jul 22 Javascript
javascript条件式访问属性和箭头函数介绍
Nov 17 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中MVC的开发经验分享
2012/05/17 PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
2013/06/13 PHP
php字符串函数学习之substr()
2015/03/27 PHP
php实现遍历多维数组的方法
2015/11/25 PHP
学习php设计模式 php实现享元模式(flyweight)
2015/12/07 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
基于jQuery的ajax功能实现web service的json转化
2009/08/29 Javascript
javascript对下拉列表框(select)的操作实例讲解
2013/11/29 Javascript
javaScript如何处理从java后台返回的list
2014/04/24 Javascript
JavaScript控制图片加载完成后调用回调函数的方法
2015/03/20 Javascript
深入理解jquery自定义动画animate()
2016/05/24 Javascript
基于JS实现横线提示输入验证码随验证码输入消失(js验证码的实现)
2016/10/27 Javascript
jquery组件WebUploader文件上传用法详解
2020/10/23 Javascript
理解 javascript 中的函数表达式与函数声明
2017/07/07 Javascript
BootStrap模态框和select2合用时input无法获取焦点的解决方法
2017/09/01 Javascript
移动端效果之IndexList详解
2017/10/20 Javascript
Vue表单及表单绑定方法
2018/09/04 Javascript
[00:35]DOTA2上海特级锦标赛 VP战队宣传片
2016/03/04 DOTA
在Python中利用Pandas库处理大数据的简单介绍
2015/04/07 Python
在Django框架中编写Context处理器的方法
2015/07/20 Python
Python有序字典简单实现方法示例
2017/09/28 Python
python读取配置文件方式(ini、yaml、xml)
2020/04/09 Python
Python3.8.2安装包及安装教程图文详解(附安装包)
2020/11/28 Python
利用python制作拼图小游戏的全过程
2020/12/04 Python
DNA测试:Orig3n
2019/03/01 全球购物
北京某科技有限公司C# .net笔试题
2014/09/27 面试题
工程力学专业自荐信范文
2014/03/17 职场文书
志愿者宣传口号
2014/06/17 职场文书
金融管理专业求职信
2014/07/10 职场文书
2014年预备党员群众路线教育实践活动对照检查材料思想汇报
2014/10/02 职场文书
乡镇党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
优秀教师个人材料
2014/12/15 职场文书
2015年工程部工作总结
2015/04/30 职场文书
初中团支书竞选稿
2015/11/21 职场文书
Nginx的反向代理实例详解
2021/03/31 Servers
html5移动端禁止长按图片保存的实现
2021/04/20 HTML / CSS