上基友社區看了下,發現對echarts的封裝都是打包進去的,想一想就仍是算了。javascript
圖表這貨.說實在的,若不是整個系統大量用到,打包進去不必。css
CDN是個好東西,咱們徹底能夠寫一個異步加載JS而後封裝按需調用。html
至於你能學到什麼,見仁見智了,如有所收穫就是我這文章的意義所在了 。vue
實現思路及實現的功能java
echarts
,有三個版本,不是最大也不是最小那個,具體上官網看setOption
的抽離,圖表實例化id
隨機生成或者手動傳入setOption
能夠一次性傳入整個圖表的參數,也能夠拆分傳入(太多,只選了幾個複用率很高選項的)...都設置了默認值.id
是大寫字母的組合,外部有傳入則用外部的實現Vue.use(?)es6
import echarts from "./echarts";
// Vue.use必須有install這個函數..可能我這裏寫的比較粗糙..有興趣的能夠去完善
// 用是能夠正常使用的
export default {
install: function(Vue, Option) {
Vue.component("vue-echarts", echarts);
}
};
複製代碼
<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>
複製代碼
// promise的polyfill
require("es6-promise").polyfill();
// 百度圖表
import echarts from './components/common/echarts';
Vue.use(echarts);
複製代碼
好吧,寫這個東西花了一下午的時間,從構思到去查echarts api
到實現;api
粗糙的版本已經誕生,可能還有能夠優化的地方,只能待我之後發現了再作調整了.promise
有更好的實現方案和思路的能夠往下面留言。app