欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-12-30 09:12:54
需求背景:dashboard作为目前企业中后台产品的“门面”,如何更加实时、高效、炫酷的对统计数据进行展示,是值得前端开发工程师和ui设计师共同思考的一个问题。今天就从0开...

需求背景: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组件的教程详解,希望对大家有所帮助