使用Vue开发动态刷新Echarts组件的教程详解


Posted in Javascript onMarch 22, 2018

需求背景:dashboard作为目前企业中后台产品的“门面”,如何更加实时、高效、炫酷的对统计数据进行展示,是值得前端开发工程师和UI设计师共同思考的一个问题。今天就从0开始,封装一个动态渲染数据的Echarts折线图组件,抛砖引玉,一起来思考更多有意思的组件。

准备工作

项目结构搭建

因为生产需要(其实是懒),所以本教程使用了 ==vue-cli==进行了项目的基础结构搭建。

npm install -g vue-cli
vue init webpack vue-charts
cd vue-charts
npm run dev

安装Echarts

直接使用npm进行安装。

npm install Echarts --save

引入Echarts

//在main.js加入下面两行代码
import echarts from 'echarts'
Vue.prototype.$echarts = echarts //将echarts注册成Vue的全局属性

到此,准备工作已经完成了。

静态组件开发

因为被《React编程思想》这篇文章毒害太深,所以笔者开发组件也习惯从基础到高级逐步迭代。

静态组件要实现的目的很简单,就是把Echarts图表,渲染到页面上。

新建Chart.vue文件

<template>
 <div :id="id" :style="style"></div>
</template>
<script>
export default {
 name: "Chart",
 data() {
  return {
   //echarts实例
   chart: ""  
  };
 },
 props: {
  //父组件需要传递的参数:id,width,height,option
  id: {
   type: String
  },
  width: {
   type: String,
   default: "100%"
  },
  height: {
   type: String,
   default: "300px"
  },
  option: {
   type: Object,
   //Object类型的prop值一定要用函数return出来,不然会报错。原理和data是一样的,
   //使用闭包保证一个vue实例拥有自己的一份props
   default() {
    return {
     title: {
      text: "vue-Echarts"
     },
     legend: {
      data: ["销量"]
     },
     xAxis: {
      data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子","tuoxie"]
     },
     series: [
      {
       name: "销量",
       type: "line",
       data: [5, 20, 36, 10, 10, 70]
      }
     ]
    };
   }
  }
 },
 computed: {
  style() {
   return {
    height: this.height,
    width: this.width
   };
  }
 },
 mounted() {
  this.init();
 },
 methods: {
  init() {
   this.chart = this.$echarts.init(document.getElementById(this.id));
   this.chart.setOption(this.option);
  }
 }
};
</script>

上述文件就实现了将一个简单折线图渲染到页面的组件,怎么样是不是很简单?最简使用方法如下:

App.vue

<template>
 <div id="app">
  <Chart id="test"/>
 </div>
</template>
<script>
import Chart from "./components/Chart";
export default {
 name: "App",
 data() {},
 components: {
  Chart
 }
}
</script>

至此,运行程序你应该能看到以下效果:

使用Vue开发动态刷新Echarts组件的教程详解 

第一次迭代

现在我们已经有了一个基础版本,让我们来看看哪些方面做的还不尽如人意:

  1. 图表无法根据窗口大小进行自动缩放,虽然设置了宽度为100%,但是只有刷新页面图表才会重新进行渲染,这会让用户体验变得很差。
  2. 图表目前无法实现数据自动刷新

下面我们来实现这两点:

自动缩放

Echarts本身是不支持自动缩放的,但是Echarts为我们提供了resize方法。

//在init方法中加入下面这行代码
window.addEventListener("resize", this.chart.resize);

只需要这一句,我们就实现了图表跟随窗口大小自适应的需求。

支持数据自动刷新

因为Echarts是数据驱动的,这意味着只要我们重新设置数据,那么图表就会随之重新渲染,这是实现本需求的基础。我们再设想一下,如果想要支持数据的自动刷新,必然需要一个监听器能够实时监听到数据的变化然后告知Echarts重新设置数据。所幸Vue为我们提供了==watcher==功能,通过它我们可以很方便的实现上述功能:

//在Chart.vue中加入watch
 watch: {
  //观察option的变化
  option: {
   handler(newVal, oldVal) {
    if (this.chart) {
     if (newVal) {
      this.chart.setOption(newVal);
     } else {
      this.chart.setOption(oldVal);
     }
    } else {
      this.init();
    }
   },
   deep: true //对象内部属性的监听,关键。
  }
 }

上面代码就实现了我们对option对象中属性变化的监听,一旦option中的数据有了变化,那么图表就会重新渲染。

实现动态刷新

下一步我想大家都知道了,就是定时从后台拉取数据,然后更新父组件的option就好。这个地方有两个问题需要思考一下:

  1. 如果图表要求每秒增加一个数据,应该如何进行数据的请求才能达到性能与用户体验的平衡?
  2. 动态更新数据的代码,应该放在父组件还是子组件?

对第一个问题,每秒实时获取服务器的数据,肯定是最精确的,这就有两种方案:

  • 每秒向后台请求一次
  • 保持长连接,后台每秒向前端推送一次数据

第一种方案无疑对性能和资源产生了极大的浪费;除非实时性要求特别高(股票系统),否则不推荐这种方式;

第二种方案需要使用web Socket,但在服务端需要进行额外的开发工作。

笔者基于项目的实际需求(实时性要求不高,且后台生成数据也有一定的延迟性),采用了以下方案:

  1. 前端每隔一分钟向后台请求一次数据,且为当前时间的上一分钟的数据;
  2. 前端将上述数据每隔一秒向图表set一次数据

关于第二个问题:笔者更倾向于将Chart组件设计成纯组件,即只接收父组件传递的数据进行变化,不在内部进行复杂操作;这也符合目前前端MVVM框架的最佳实践;而且若将数据传递到Chart组件内部再进行处理,一是遇到不需要动态渲染的需求还需要对组件进行额外处理,二是要在Chart内部做ajax操作,这样就导致Chart完全没有了可复用性。

接下来我们修改App.vue

<template>
 <div id="app">
  <Chart id="test" :option="option"/>
 </div>
</template>

<script>
import vueEcharts from "./components/vueEcharts";
export default {
 name: "App",
 data() {
  return {
   //笔者使用了mock数据代表从服务器获取的数据
   chartData: {
    xData: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
    sData: [5, 20, 36, 10, 10, 70]
   }
  };
 },
 components: {
  Chart
 },
 mounted() {
  this.refreshData();
 },
 methods: {
  //添加refreshData方法进行自动设置数据
  refreshData() {
   //横轴数据
   let xData = this.chartData.xData,
    //系列值
     sData = this.chartData.sData;
   for (let i = 0; i < xData.length; i++) {
    //此处使用let是关键,也可以使用闭包。原理不再赘述
      setTimeout(() => {
     this.option.xAxis.data.push(xData[i]);
     this.option.series[0].data.push(sData[i]);
    }, 1000*i)//此处要理解为什么是1000*i
   }
  }
 }
};
</script>

至此我们就实现了图表动态数据加载,效果如下图:

 使用Vue开发动态刷新Echarts组件的教程详解

总结

这篇教程通过一个动态图表的开发,传递了以下信息:

  • Echarts如何与Vue结合使用
  • Vue组件开发、纯组件与“脏”组件的区别
  • Vue watch的用法
  • let的特性
  • JavaScript EventLoop特性
  • ...

大家可以根据这个列表查漏补缺。

后续优化

  1. 这个组件还有需要需要优化的点,比如:
  2. 间隔时间应该可配置
  3. 每分钟从后台获取数据,那么图表展示的数据将会越来越多,越来越密集,浏览器负担越来越大,直到崩溃
  4. 没有设置暂停图表刷新的按钮
  5. ...

总结

以上所述是小编给大家介绍的使用Vue开发动态刷新Echarts组件的教程详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery模拟超链接点击效果代码
Apr 21 Javascript
div模拟选择框示例代码
Nov 03 Javascript
setTimeout()与setInterval()方法区别介绍
Dec 24 Javascript
js加载读取内容及显示与隐藏div示例
Feb 13 Javascript
JavaScript数组对象实现增加一个返回随机元素的方法
Jul 27 Javascript
jQuery Validate插件实现表单强大的验证功能
Dec 18 Javascript
基于HTML5上使用iScroll实现下拉刷新,上拉加载更多
May 21 Javascript
详解Angular5路由传值方式及其相关问题
Apr 28 Javascript
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
Mar 28 Javascript
原生JS实现相邻月份日历
Oct 13 Javascript
Node快速切换版本、版本回退(降级)、版本更新(升级)
Jan 07 Javascript
微信小程序实现录音Record功能
May 09 Javascript
JavaScript分步实现一个出生日期的正则表达式
Mar 22 #Javascript
vuex 的简单使用
Mar 22 #Javascript
Vue.js中的computed工作原理
Mar 22 #Javascript
解决在Bootstrap模糊框中使用WebUploader的问题
Mar 22 #Javascript
JS中的事件委托实例浅析
Mar 22 #Javascript
jquery的 filter()方法使用教程
Mar 22 #jQuery
p5.js实现斐波那契螺旋的示例代码
Mar 22 #Javascript
You might like
使用php get_headers 判断URL是否有效的解决办法
2013/04/27 PHP
PHP删除目录及目录下所有文件的方法详解
2013/06/06 PHP
PHP从FLV文件获取视频预览图的方法
2015/03/12 PHP
PHP动态柱状图实现方法
2015/03/30 PHP
PHP笛卡尔积实现算法示例
2018/07/30 PHP
JSONP 跨域访问代理API-yahooapis实现代码
2012/12/02 Javascript
Extjs4中Form的使用之本地hiddenfield
2013/11/26 Javascript
jqplot通过ajax动态画折线图的方法及思路
2013/12/08 Javascript
eclipse导入jquery包后报错的解决方法
2014/02/17 Javascript
究竟什么是Node.js?Node.js有什么好处?
2015/05/29 Javascript
第九章之路径分页标签与徽章组件
2016/04/25 Javascript
jQuery实现的仿百度,仿谷歌搜索下拉框效果示例
2016/12/30 Javascript
详解JSON和JSONP劫持以及解决方法
2019/03/08 Javascript
jQuery实现计算器功能
2020/10/19 jQuery
在vant中使用时间选择器和popup弹出层的操作
2020/11/04 Javascript
element-ui 弹窗组件封装的步骤
2021/01/22 Javascript
详解React中共享组件逻辑的三种方式
2021/02/02 Javascript
[49:42]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#2Secret VS EG第一局
2016/03/04 DOTA
[01:03:56]Mineski vs TNC 2018国际邀请赛淘汰赛BO1 8.21
2018/08/22 DOTA
Python中对象的引用与复制代码示例
2017/12/04 Python
python http接口自动化脚本详解
2018/01/02 Python
python实现快速排序的示例(二分法思想)
2018/03/12 Python
python如何创建TCP服务端和客户端
2018/08/26 Python
Django跨域请求CSRF的方法示例
2018/11/11 Python
python GUI库图形界面开发之PyQt5窗口布局控件QStackedWidget详细使用方法
2020/02/27 Python
python 函数嵌套及多函数共同运行知识点讲解
2020/03/03 Python
英国Amara家居法国网站:家居装饰,现代装饰和豪华礼品
2016/12/15 全球购物
俄罗斯电子产品、计算机和家用电器购物网站:OLDI
2019/10/27 全球购物
通信专业个人自我鉴定
2013/10/21 职场文书
竞选演讲稿范文大全
2014/05/12 职场文书
财务负责人岗位职责
2015/02/03 职场文书
超搞笑婚前保证书
2015/05/08 职场文书
导游词之晋城蟒河
2019/12/12 职场文书
浅谈pytorch中的dropout的概率p
2021/05/27 Python
SpringDataJPA实体类关系映射配置方式
2021/12/06 Java/Android
漫画「古见同学有交流障碍症」第25卷封面公开
2022/03/21 日漫