使用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与Prototype并存的冲突的解决方法
Aug 29 Javascript
extjs render 用法介绍
Sep 11 Javascript
js加载之使用DOM方法动态加载Javascript文件
Nov 08 Javascript
scrollWidth,clientWidth,offsetWidth的区别
Jan 13 Javascript
jQuery实现灰蓝风格标准二级下拉菜单效果代码
Aug 31 Javascript
javascript函数式编程程序员的工具集
Oct 11 Javascript
十分钟带你快速了解React16新特性
Nov 10 Javascript
前端MVVM框架解析之双向绑定
Jan 24 Javascript
vue+springboot前后端分离实现单点登录跨域问题解决方法
Jan 30 Javascript
Vue Object.defineProperty及ProxyVue实现双向数据绑定
Sep 02 Javascript
JS实现无限轮播无倒退效果
Sep 21 Javascript
详解template标签用法(含vue中的用法总结)
Jan 12 Vue.js
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 XML备份Mysql数据库
2009/05/27 PHP
PHP中如何判断AJAX提交的数据
2012/02/05 PHP
PHP上传文件时文件过大$_FILES为空的解决方法
2013/11/26 PHP
PHP中绘制图像的一些函数总结
2014/11/19 PHP
PHP之将POST数据转化为字符串的实现代码
2016/11/03 PHP
php使用Jpgraph创建折线图效果示例
2017/02/15 PHP
PHP实现动态删除XML数据的方法示例
2018/03/30 PHP
laravel5.6 框架邮件队列database驱动简单demo示例
2020/01/26 PHP
Jquery 模板数据绑定插件的使用方法详解
2013/07/08 Javascript
js日期、星座的级联显示代码
2014/01/23 Javascript
利用函数的惰性载入提高javascript代码执行效率
2014/05/05 Javascript
JavaScript中的null和undefined区别介绍
2015/01/01 Javascript
jQuery实现表格行上下移动和置顶效果
2015/06/05 Javascript
网页前端登录js按Enter回车键实现登陆的两种方法
2016/05/10 Javascript
使用jQuery实现WordPress中的Ctrl+Enter和@评论回复
2016/05/21 Javascript
浅析BootStrap栅格系统
2016/06/07 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
2017/08/17 jQuery
js属性对象的hasOwnProperty方法的使用
2021/02/05 Javascript
实例讲解Python的函数闭包使用中应注意的问题
2016/06/20 Python
python中的格式化输出用法总结
2016/07/28 Python
python3实现抓取网页资源的 N 种方法
2017/05/02 Python
Python实现字符串反转的常用方法分析【4种方法】
2017/09/30 Python
Python爬虫之正则表达式的使用教程详解
2018/10/25 Python
PyCharm+Qt Designer+PyUIC安装配置教程详解
2019/06/13 Python
python jenkins 打包构建代码的示例代码
2019/11/29 Python
使用darknet框架的imagenet数据分类预训练操作
2020/07/07 Python
俄语地区最大的中国商品在线购物网站之一:Umka Mall
2019/11/03 全球购物
技术总监管理职责范本
2014/03/06 职场文书
学校党员干部承诺书
2015/05/04 职场文书
小英雄雨来观后感
2015/06/09 职场文书
校园广播稿范文
2015/08/19 职场文书
2019中小学生安全过暑期倡议书
2019/06/24 职场文书
行政后勤人员工作计划应该怎么写?
2019/08/16 职场文书
如何用Node.js编写内存效率高的应用程序
2021/04/30 Javascript
教你利用python实现企业微信发送消息
2021/05/23 Python
Python 数据结构之十大经典排序算法一文通关
2021/10/16 Python