前言
上基友社区看了下,发现对echarts的封装都是打包进去的,想想就还是算了。
图表这货.说实在的,若不是整个系统大量用到,打包进去没必要。
CDN是个好东西,我们完全可以写一个异步加载JS然后封装按需调用。
至于你能学到什么,见仁见智了,若有所收获就是我这文章的意义所在了 。
效果图
实现思路及实现的功能
- 异步引入
echarts
,有三个版本,不是最大也不是最小那个,具体上官网看 - 图表的销毁释放内存
- 图表跟随父包含块自适应(事件监听)
setOption
的抽离,图表实例化id
随机生成或者手动传入setOption
可以一次性传入整个图表的参数,也可以拆分传入(太多,只选了几个复用率很高选项的)...都设置了默认值.- 随机
id
是大写字母的组合,外部有传入则用外部的
代码
实现Vue.use(?)
index.js -- 导出组件的,内部实在亮瞎眼
import echarts from "./echarts"; // Vue.use必须有install这个函数..可能我这里写的比较粗糙..有兴趣的可以去完善 // 用是可以正常使用的 export default { install: function(Vue, Option) { Vue.component("vue-echarts", echarts); } };
echarts.vue
<template> <div class="vue-echarts" :id="id" :style="style"> </div> </template> <script> export default { name: 'vue-echarts', data: function () { return { loadJS: '', // 存储异步加载echart的promise状态 chart: '', // 保存地图初始化的实例 } }, props: { id: { type: String, default: function () { // 生成一个随机字符串,纯英文的,当不传入ID的时候生成实例,加i确保不会随机到一样的 let temp = []; for (let i = 0; i < 6; i++) { let randomChar = String.fromCharCode(65 + Math.floor(Math.random() * 19) + i); temp.push(randomChar); } return temp.reduce((pre, next) => pre + next); } }, height: { // 图表高度 type: String, default: '300px' }, width: { // 图表宽度 type: String, default: '100%' }, legend: { // 以下的配置都是echarts官方图表的自定义部分,我拆分这么几大块 type: Object, default: function () { return { data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'] } } }, title: { type: Object, default: function () { return { text: '堆叠区域图' } } }, tooltip: { type: [Array, Object], default: function () { return { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' }, animation: true } } } }, toolbox: { type: Object, default: function () { return { show: true, feature: { dataZoom: { yAxisIndex: 'none' }, dataView: { readOnly: false }, magicType: { type: ['line', 'bar'] }, restore: {}, saveAsImage: {} } } } }, grid: { type: Object, default: function () { return { left: '3%', right: '4%', bottom: '3%', containLabel: true } } }, xAxis: { type: [Array, Object], default: function () { return [ { type: 'category', boundaryGap: true, data: ['00:00', '02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00', '24:00'] } ] } }, yAxis: { type: [Array, Object], default: function () { return [ { type: 'value' } ] } }, series: { type: [Array, Object], default: function () { return [ { name: '曝光', type: 'line', smooth: true, lineStyle: { normal: { color: '#f00', } }, data: [120, 132, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 120] }, { name: '点击', type: 'line', smooth: true, lineStyle: { normal: { color: '#20a0ff', } }, data: [220, 182, 191, 234, 290, 330, 310, 120, 132, 101, 134, 90, 120] }, { name: '点击率', type: 'line', lineStyle: { normal: { color: '#42b983', } }, smooth: true, data: [150, 232, 201, 154, 190, 330, 410, 120, 132, 101, 134, 90, 120] } ] } }, setOption: { type: Object }, dispose: Boolean }, computed: { style () { return { height: this.height, width: this.width } } }, created () { this.loadJS = this.loadEchartsJS(); }, mounted () { this.loadJS.then(() => { let st = setTimeout(() => { this.init(); // CDNJS加载后,元素渲染后,初始化图表 }, 300); }).catch(err => { console.log('echarts js加载失败'); }); }, beforeDestroy () { window.removeEventListener('resize', this.chart.resize) if (this.chart) { this.chart.dispose(); // 销毁图表实例 } }, methods: { init () { // 初始化图表 this.chart = new echarts.init(document.getElementById(this.id)); this.chart.setOption(this.setOption); window.addEventListener('resize', this.chart.resize) // 图表响应大小的关键,重绘 }, loadEchartsJS () { // 异步请求cdnjs const CDNURL = 'https://cdn.bootcss.com/echarts/3.7.1/echarts.min.js'; return new Promise((resolve, reject) => { const script = document.createElement('script'); script.type = "text/javascript"; script.id = "cdnEchart"; if (script.readyState) { //IE script.onreadystatechange = function () { if (script.readyState == "loaded" || script.readyState == "complete") { script.onreadystatechange = null; resolve('success: ' + CDNURL); } }; } else { //Others script.onload = function () { resolve('success: ' + CDNURL); }; } script.onerror = function () { reject(Error(CDNURL + 'load error!')); }; script.src = CDNURL; if (!document.getElementById('cdnEchart')) { document.head.appendChild(script); } }); } }, watch: { setOption: { handler: function (newVal, oldVal) { // 监听外部传入的值,渲染新的的图表数据 if (this.chart) { if (newVal) { this.chart.setOption(newVal); } else { this.chart.setOption(oldVal); } this.chart.resize(); } else { setTimeout(() => { this.init(); }, 300); } }, deep: true } } } </script>
如何使用
- main.js -- 主入口文件,
// promise的polyfill require("es6-promise").polyfill(); // 百度图表 import echarts from './components/common/echarts'; Vue.use(echarts);