vue2简单封装highcharts

  • 前言
  • 一、vue文件(high-chart.vue)
  • 二、highcharts配置(default-options.js)
  • 三、包裹highcharts的div宽度变化时,需要重绘,因此需要监听el
    • 1、resize-event.js
    • 2、debounce.js
  • 四、依赖库版本(package.json)

前言

把highcharts封装成vue组件,任何项目用起来都很方便


一、vue文件(high-chart.vue)

<template><div class="highcharts-container" />
</template><script>
import * as _ from 'lodash';
import HighCharts from 'highcharts/highstock';
import HighchartsMore from 'highcharts/highcharts-more';
import HighchartsDrilldown from 'highcharts/modules/drilldown';
import Highcharts3D from 'highcharts/highcharts-3d';
import Exporting from 'highcharts/modules/exporting.js';
import HighchartsNoData from 'highcharts-no-data-to-display';
import defaultOptions from '_c/chart/default-options';
import Annotations from 'highcharts/modules/annotations.js';
import Oldie from 'highcharts/modules/oldie.js';
import { addResizeListener, removeResizeListener } from '@/utils/resize-event.js';
import debounce from '@/utils/debounce.js';HighchartsMore(HighCharts);
HighchartsDrilldown(HighCharts);
Highcharts3D(HighCharts);
Exporting(HighCharts);
Annotations(HighCharts);
Oldie(HighCharts);
HighchartsNoData(HighCharts);HighCharts.setOptions({global: {timezoneOffset: -8 * 60,},lang: {noData: '数据未上报',viewFullscreen: '全屏查看',printChart: '打印图表',downloadJPEG: '下载JPEG 图片',downloadPDF: '下载PDF文档',downloadPNG: '下载PNG 图片',downloadSVG: '下载SVG 矢量图',exportButtonTitle: '导出图片',loading: '加载中...',resetZoom: '重置视图',},
});export default {name: 'high-chart',props: {options: {type: Object,default: () => {},},series: {type: Array,default: () => [],},loading: {type: Boolean,default: () => false,},},data() {return {     chart: null,};},computed: {finalOptions() {return _.merge(_.cloneDeep(defaultOptions), this.options);},},watch: {options: {handler() {this.chart && this.chart.update(this.finalOptions);        },deep: true,},loading(v) {if (v && this.chart) {this.chart.showLoading();} else if (!v && this.chart) {this.chart.hideLoading();}},series: {handler(newVal) {if (newVal?.length) {this.updateSeries();} else {this.initChart();}},},},mounted() {this.initChart();addResizeListener(this.$el, this.onResize());},beforeDestroy() {this.chart && this.chart.destroy();this.chart = null;},destroyed() {removeResizeListener(this.$el, this.onResize());},methods: {onResize() {return debounce(() => {this.chart && this.chart.reflow();}, 200);},initChart() {this.chart = new HighCharts.chart(this.$el, this.finalOptions);window.chart = this.chart;if (this.loading) {this.chart.showLoading();}this.updateSeries();},updateSeries() {if (!this.chart) {return;}this.series.forEach((series) => {const exist = this.chart.get(series.id);if (exist) {exist.setData(series.data, false);exist.setVisible(true, false);exist.update({diffDay: series.diffDay,visible: series.visible,showInLegend: series.showInLegend,type: series.type,},false,);} else {this.chart.addSeries(series, false);}});this.chart.series.forEach((series) => {if (!this.series.find((s) => s.name === series.name)) {series.setVisible(false, false);series.update({ showInLegend: false, type: series.type }, false);}});this.chart.redraw();},},
};
</script><style lang="less" scoped>
@import '@/style/index';.highcharts-container {display: block;& /deep/ .highcharts-container {margin: 0 auto;}
}
</style>

二、highcharts配置(default-options.js)

export default {chart: {spacingBottom: 5,spacingLeft: 0,height: 300,},colors: ['#0000ff','#ff9a38','#3ecc36','#ff5620','#7953ff','#1ee6e6','#1be591','#db30ff','#ff3383','#33c4ff','#ffc500',],title: {style: {fontSize: '14px',textOverflow: 'ellipsis',wordBreak: 'break-all',wordWrap: 'break-word',// visibility: 'hidden',},text: '',},xAxis: {gridLineWidth: 1,tickPixelInterval: 40, // 刻度间距type: 'datetime',dateTimeLabelFormats: {millisecond: '%H:%M:%S.%L',second: '%H:%M:%S',minute: '%H:%M',hour: '%H',day: '%m-%d',week: '%m-%d',month: '%Y-%m',year: '%Y',},labels: {rotation: -45,},plotBands: [// {//   color: '#FFD4C5',//   from: 1635726000000,//   to: 1635736800000,//   label: {//     text: '异常',//   },// },],},yAxis: [{gridLineWidth: 1,// tickAmount: null, // 规定坐标轴上的刻度总数endOnTick: false, // 是否强制将坐标轴结束于刻度线startOnTick: false,ceiling: null, // 自动计算坐标轴极值的上限// softMax: 1, // 坐标轴的柔和最大值title: {text: '',style: {fontWeight: 'bold',fontSize: '12px',},align: 'high',rotation: 0,offset: 0,y: -20,x: 6,},labels: {align: 'right',padding: 0,},height: '100%',},{gridLineWidth: 0,// tickAmount: null, // 规定坐标轴上的刻度总数endOnTick: false, // 是否强制将坐标轴结束于刻度线startOnTick: false,ceiling: null, // 自动计算坐标轴极值的上限// softMax: 1, // 坐标轴的柔和最大值title: {text: '',style: {fontWeight: 'bold',fontSize: '12px',},align: 'high',rotation: 0,offset: 0,y: -20,x: 6,},labels: {align: 'left',padding: 0,},opposite: true,top: '100%',height: '0%',},],tooltip: {enabled: true,shared: true,crosshairs: true,dateTimeLabelFormats: {millisecond: '%H:%M',second: '%H:%M',minute: '%H:%M',hour: '%H:%M',day: '%m-%d',week: '%m-%d',month: '%Y-%m',},useHTML: true,},credits: {enabled: false,},legend: {layout: 'horizontal',align: 'center',verticalAlign: 'bottom',enabled: true,margin: 0,padding: 0,// itemWidth: 120,symbolWidth: 10,itemStyle: {fontSize: '11px',},},exporting: {enabled: false,buttons: {contextButton: {menuItems: [],},},},plotOptions: {line: {lineWidth: 1,states: {hover: {lineWidth: 2,},},marker: {enabled: false,symbol: 'diamond',},},spline: {lineWidth: 1,states: {hover: {lineWidth: 2,},},marker: {enabled: false,symbol: 'diamond',},},area: {marker: {enabled: false,},},column: {minPointLength: 10,borderWidth: 0,pointWidth: 10,// pointPadding: 50,// groupPadding: 50,dataLabels: {enabled: true,},},series: {states: {inactive: {enabled: false,},},},},annotations: [],series: [],responsive: {// 通过设定不同的响应规则来实现对图表在不同尺寸下的响应rules: [{condition: {maxWidth: 500,},chartOptions: {legend: {layout: 'horizontal',align: 'center',verticalAlign: 'bottom',},},},],},
};

三、包裹highcharts的div宽度变化时,需要重绘,因此需要监听el

1、resize-event.js

import ResizeObserver from 'resize-observer-polyfill';
/* istanbul ignore next */
// eslint-disable-next-line func-names
const resizeHandler = function (entries) {// eslint-disable-next-line no-restricted-syntaxfor (const entry of entries) {const listeners = entry.target.__resizeListeners__ || [];if (listeners.length) {listeners.forEach((fn) => {fn();});}}
};/* istanbul ignore next */
// eslint-disable-next-line func-names
export const addResizeListener = function (element, fn) {if (!element.__resizeListeners__) {// eslint-disable-next-line no-param-reassignelement.__resizeListeners__ = [];// eslint-disable-next-line no-param-reassignelement.__ro__ = new ResizeObserver(resizeHandler);element.__ro__.observe(element);}element.__resizeListeners__.push(fn);
};/* istanbul ignore next */
// eslint-disable-next-line func-names
export const removeResizeListener = function (element, fn) {if (!element || !element.__resizeListeners__) return;element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);if (!element.__resizeListeners__.length) {element.__ro__.disconnect();}
};// eslint-disable-next-line func-names
export const clearResizeListener = function (element) {if (!element || !element.__resizeListeners__) return;// eslint-disable-next-line no-param-reassignelement.__resizeListeners__ = [];element.__ro__.disconnect();
};

2、debounce.js

// Some functions take a variable number of arguments, or a few expected
// arguments at the beginning and then a variable number of values to operate
// on. This helper accumulates all remaining arguments past the function’s
// argument length (or an explicit `startIndex`), into an array that becomes
// the last argument. Similar to ES6’s "rest parameter".
// eslint-disable-next-line func-names
const restArguments = function (func, startIndex) {// eslint-disable-next-line no-param-reassignstartIndex = startIndex == null ? func.length - 1 : +startIndex;// eslint-disable-next-line func-namesreturn function () {const length = Math.max(arguments.length - startIndex, 0);const rest = Array(length);let index = 0;for (; index < length; index++) {// eslint-disable-next-line prefer-rest-paramsrest[index] = arguments[index + startIndex];}// eslint-disable-next-line default-caseswitch (startIndex) {case 0:return func.call(this, rest);// eslint-disable-next-line prefer-rest-paramscase 1:return func.call(this, arguments[0], rest);// eslint-disable-next-line prefer-rest-paramscase 2:return func.call(this, arguments[0], arguments[1], rest);}const args = Array(startIndex + 1);for (index = 0; index < startIndex; index++) {// eslint-disable-next-line prefer-rest-paramsargs[index] = arguments[index];}args[startIndex] = rest;return func.apply(this, args);};
};
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
const delay = restArguments((func, wait, args) => {return setTimeout(() => {// eslint-disable-next-line prefer-spreadreturn func.apply(null, args);}, wait);
});
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
// eslint-disable-next-line func-names
const debounce = function (func, wait, immediate) {let timeout;let result;// eslint-disable-next-line func-namesconst later = function (context, args) {timeout = null;if (args) result = func.apply(context, args);};// eslint-disable-next-line func-namesconst debounced = restArguments(function (args) {if (timeout) clearTimeout(timeout);if (immediate) {const callNow = !timeout;timeout = setTimeout(later, wait);if (callNow) result = func.apply(this, args);} else {timeout = delay(later, wait, this, args);}return result;});// eslint-disable-next-line func-namesdebounced.cancel = function () {clearTimeout(timeout);timeout = null;};return debounced;
};export default debounce;

四、依赖库版本(package.json)

{"name": "tdesign-web-vue2-template","version": "0.0.1","scripts": {"dev:mock": "vite --open --mode mock","dev": "vite --open --mode development","dev:linux": "vite --mode developmenet","build:test": "vite build --mode test","build": "vite build --mode release","serve": "vite preview","lint": "eslint --ext .vue,.js,.jsx,.ts,.tsx ./ --max-warnings 0","lint:fix": "eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix","stylelint": "stylelint src/**/*.{html,vue,sass,less}","stylelint:fix": "stylelint --cache --fix src/**/*.{html,vue,vss,sass,less}","test": "jest --coverage"},"dependencies": {"@types/lodash": "^4.14.176","@vitejs/plugin-legacy": "^1.5.3","dayjs": "^1.10.6","highcharts": "^9.3.3","highcharts-no-data-to-display": "^0.1.7","insert-css": "^2.0.0","lint-staged": "^10.5.4","lodash": "^4.17.21","nprogress": "^0.2.0","qrcode.vue": "^1.7.0","resize-observer-polyfill": "^1.5.1","tdesign-icons-vue": "^0.0.8","tdesign-vue": "^0.41.3","typescript": "^4.2.4","vite-plugin-vue2-svg": "^0.1.8","vue": "^2.6.11","vuedraggable": "^2.24.3","vuex": "^3.6.2"},"devDependencies": {"@babel/core": "^7.16.0","@babel/preset-env": "^7.16.4","@babel/preset-typescript": "^7.16.0","@commitlint/cli": "^12.0.1","@commitlint/config-conventional": "^12.0.1","@rollup/plugin-dynamic-import-vars": "^1.1.1","@types/jest": "^27.0.3","@typescript-eslint/eslint-plugin": "^4.19.0","@typescript-eslint/parser": "^4.19.0","@vue/test-utils": "^1.3.0","axios": "^0.21.1","babel-jest": "^27.4.2","commitizen": "^4.2.3","eslint": "^7.22.0","eslint-config-airbnb-base": "^14.2.1","eslint-config-prettier": "^8.3.0","eslint-import-resolver-alias": "^1.1.2","eslint-plugin-import": "^2.22.1","eslint-plugin-vue": "^7.8.0","http-proxy-agent": "^4.0.1","husky": "^4.2.5","jest": "^27.4.3","less": "^4.1.0","less-loader": "^7.2.1","less-vars-to-js": "^1.3.0","mockjs": "^1.1.0","prettier": "^2.3.2","rollup-plugin-visualizer": "^5.5.4","stylelint": "^13.13.1","stylelint-config-airbnb": "0.0.0","stylelint-order": "^4.1.0","stylelint-scss": "^3.20.1","ts-jest": "^27.1.0","vite": "2.5.10","vite-plugin-environment": "^1.1.0","vite-plugin-mock": "^2.3.0","vite-plugin-theme": "^0.8.1","vite-plugin-vue2": "^1.2.2","vue-clipboard2": "^0.3.1","vue-jest": "^3.0.7","vue-router": "^3.5.1","vuex-router-sync": "^5.0.0"},"config": {"commitizen": {"path": "./node_modules/cz-conventional-changelog"}},"bit": {"env": {},"componentsDefaultDirectory": "components/{name}","packageManager": "npm"}
}

vue2简单封装highcharts相关推荐

  1. Android APP更新下载工具类——简单封装DownloadManager

    几乎所有APP都包含了检查更新功能,更新下载功能的实现方式常用的有两种:1.使用App网络框架的文件下载请求:2.使用自带的DownloadManager类:本文介绍第二种,简单封装一下Downloa ...

  2. 简单封装浏览器 cookie 工具类

    版权声明:本文首发 http://asing1elife.com ,转载请注明出处. https://blog.csdn.net/asing1elife/article/details/8265571 ...

  3. 小程序简单封装 request 请求

    我在这里做了详细的介绍 : 小程序简单封装 request 请求 转载于:https://www.cnblogs.com/biangz/p/9984340.html

  4. 简单封装 HTTP 请求

    2017-2-19 更新到第二版: 源码地址:http://git.oschina.net/sp42/ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/net ...

  5. 【JDBC】实现对JDBC 连接的简单封装

    package util;import java.sql.Connection; import java.sql.DriverManager;/**** 实现对JDBC 的封装* @author mq ...

  6. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  7. ios开发之使用多文件上传的简单封装最原始的

    ios开发之使用多文件上传的简单封装最原始的 // // ViewController.m // 18-上传多个文件 // // Created by 鲁军 on 2021/2/13. //#impo ...

  8. Spring jdbc 对象Mapper的简单封装

    一般查询实体的时候,都需要这么使用/**      * 根据id查询      *       * @return      */     public Emp queryEmpById(Intege ...

  9. Google图片加载库Glide的简单封装GlideUtils

    Google图片加载库Glide的简单封装GlideUtils  

最新文章

  1. q-LDPC实验进展
  2. 【Android 逆向】arm 汇编 ( 使用 IDA 解析 arm 架构的动态库文件 | 分析 malloc 函数的 arm 汇编语言 )
  3. 【杂谈】从学员到参与书籍写作,我在有三AI学习与成长的故事
  4. java登录界面命令_Java命令行界面(第5部分):JewelCli
  5. dubbo + zookeeper 简介和部署
  6. jPList – 实现灵活排序和分页功能的 jQuery 插件
  7. Git中的“起源”是什么?
  8. php中的三元运算符
  9. SqlServer 2008R2修改表结构提示“不允许保存更改”解决方案
  10. 实时取色器(RGB)
  11. 不同类别游戏音效的特点
  12. JAVA实现EXCEL公式专题(七)——统计函数
  13. 2048游戏回顾三:自定义Dialog和ProgressBar
  14. 达梦数据库远程网页访问
  15. nssa和stub_OSPF的特殊区域--stub及totally-stub及nssa及totally-nssa详解
  16. 浅析SkipList跳跃表原理及代码实现
  17. iOS 防止截屏、录屏技术
  18. zabbix配置监控主机及微信报警功能
  19. 腾讯短链接在线生成工具
  20. 数据挖掘 沪深股市预测

热门文章

  1. 百度网盘自动发货机器人软件助手(可用于虚拟店自动发货场景)
  2. 枣庄在线备授课系统找不到服务器,智能备授课平台工具官方版
  3. HCNP RoutingSwitching之MAC安全
  4. 人类附身机器人获得永生_2045年人类将永生不死,用纳米机器人改造人体以获长生...
  5. prompt和instruct的区别究竟是什么
  6. c语言简单的英汉词典系统
  7. 什么是LRU(最近最少使用)算法?
  8. 【华人学者风采】裴健 加拿大西蒙弗雷泽大学
  9. [菜鸟向]使用ZeroTier实现内网穿透,校外连接实验室服务器
  10. 全开源的自动化立体智慧仓库系统源码,基于SpringBoot开发