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 相关文章推荐
利用404错误页面实现UrlRewrite的实现代码
Aug 20 Javascript
jquery实现标题字体变换的滑动门菜单效果
Sep 07 Javascript
JavaScript获取页面中超链接数量的方法
Nov 09 Javascript
Bootstrap弹出框(Popover)被挤压的问题小结
Jul 11 Javascript
使用vux实现上拉刷新功能遇到的坑
Feb 08 Javascript
vue内置组件transition简单原理图文详解(小结)
Jul 12 Javascript
2019 年编写现代 JavaScript 代码的5个小技巧(小结)
Jan 15 Javascript
JavaScript使用闭包模仿块级作用域操作示例
Jan 21 Javascript
微信小程序+云开发实现欢迎登录注册
May 24 Javascript
小程序实现长按保存图片的方法
Dec 31 Javascript
JavaScript对象属性操作实例解析
Feb 04 Javascript
小程序自定义导航栏兼容适配所有机型(附完整案例)
Apr 26 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中使用PDF文档功能
2006/10/09 PHP
关于Iframe如何跨域访问Cookie和Session的解决方法
2013/04/15 PHP
PIGCMS 如何关闭聊天机器人
2015/02/12 PHP
php支付宝在线支付接口开发教程
2016/09/19 PHP
php中通过eval实现字符串格式的计算公式
2017/03/18 PHP
thinkPHP框架实现的短信接口验证码功能示例
2018/06/20 PHP
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
2012/09/14 Javascript
js实现通用的微信分享组件示例
2014/03/10 Javascript
js判断空对象的实例(超简单)
2016/07/26 Javascript
浅谈javascript中的 “ &amp;&amp; ” 和 “ || ”
2017/02/02 Javascript
jQuery实现select下拉框获取当前选中文本、值、索引
2017/05/08 jQuery
深入理解vue $refs的基本用法
2017/07/13 Javascript
使用Nodejs连接mongodb数据库的实现代码
2017/08/21 NodeJs
Express使用html模板的详细代码
2017/09/18 Javascript
浅谈v-for 和 v-if 并用时筛选条件方法
2019/11/07 Javascript
javascript/jquery实现点击触发事件的方法分析
2019/11/11 jQuery
es6函数之箭头函数用法实例详解
2020/04/25 Javascript
node中短信api实现验证码登录的示例代码
2021/01/20 Javascript
[05:02][DOTA2]DOTA进化论 第一期
2013/09/27 DOTA
[04:40]2016国际邀请赛中国区预选赛全程TOP10镜头集锦
2016/07/01 DOTA
[00:10]DOTA2全国高校联赛 以DOTA2会友
2018/05/30 DOTA
Python实现的简单模板引擎功能示例
2017/09/02 Python
H5调用相机拍照并压缩图片的实例代码
2017/07/20 HTML / CSS
Clarks鞋澳大利亚官方网站:Clarks Australia
2019/12/25 全球购物
银行自荐信范文
2013/10/07 职场文书
医药学专业大学生职业生涯规划书论文
2014/01/21 职场文书
《分一分》教学反思
2014/04/13 职场文书
贷款担保书范文
2014/05/13 职场文书
授权委托书格式
2014/07/31 职场文书
学习张林森心得体会
2014/09/10 职场文书
2014党员学习《反腐倡廉警示教育读本》思想汇报
2014/09/13 职场文书
机关干部作风建设剖析材料
2014/10/23 职场文书
农村党建工作汇报材料
2014/10/27 职场文书
三潭印月的导游词
2015/02/12 职场文书
2015年暑期实践报告范文
2015/07/13 职场文书
JavaScript中时间格式化新思路toLocaleString()
2021/11/07 Javascript