最近在做Beetlex的資料分析平臺,在開發這個產品過程中涉及到大量的資料圖表展示功能;由於產品前端使用的是vuejs開發,所以在整合echarts或多或少會碰到一些問題,在這裡主要講解一下碰到的問題和解決方法。
在講解之前先分享一下實際使用效果。具體可以檢視 http://data.beetlex.io
控制元件ID
在vuejs中往往會對常用的功能進行元件封裝,同樣為了讓不同圖表複用所以也封裝成元件來使用。在這個封裝過程存在一個問題就是圖表元素DIV的ID問題,所以元件建構建圖表DIV的ID也必須確保唯一性。可以通過封裝一個簡單的函式來生成ID
Vue.prototype.$getID = function () { page.controlid = page.controlid + 1; return page.controlid; };
通過這個方法來獲取動態的元素ID
mounted(){ this.ChatID = "chat_" + this.$getID(); } <div :id="ChatID"> </div>
初始化問題
在使用Vuejs時很多時候會在mounted()方法中進行一些實始化,但如果在這裡實始化echarts就需要注意,畢竟mounted並不代表所有元素被構建,這時候會導致獲取元素失敗無法對echarts進行初始化操作。所以需要把echarts放到一個方法中根據情況手動呼叫進行,或者延時一下呼叫初始化;為了方便選擇使用了setTimeout來初始化。
setTimeout(() => { var dom = document.getElementById(this.ChatID); this.Chat = echarts.init(dom, 'macarons'); this.Chat.setOption(this.ChatOption, true); }, 300);
顯示切換問題
如果需要對圖表進行一個顯示切換,最好不要用v-if這樣的語法,因為這樣的語法是不會在DOM中構建相關元素,引起echarts建立Canvas元素問題導致無法正常工作。最好的辦法是通過切換Css的方式來進行顯示切換,確保已構建的DOM元素內容沒有被更改。
自適應佈局
很多時候窗體的大變化和元件切換後會導致echarts無法適應當前佈局,碰到這情況需要手動呼叫echarts的resize方法來進行重置顯示佈局。實際上在SPA應用中情況複雜很多,全屏顯示,窗體要換,再加元件化後多層次巢狀,所以難以確定echarts使用在什麼地方。為了滿足不同情況的需求,需要一個公共的行為來觸發這些變更。
var __resizeHandlers = []; function __addResizeHandler(handler) { __resizeHandlers.push(handler); }; function __resize() { setTimeout(() => { __resizeHandlers.forEach(v => { v(); }); }, 100); } window.onresize = function () { __resizeHandlers.forEach(v => { v(); }); }; Vue.prototype.$addResize = function (handler) { __addResizeHandler(handler); }; Vue.prototype.$resize = function () { __resize(); };
實現一個簡單的resize註冊和呼叫機制即可,在使用echarts的元件定義以下程式碼完美解決
this.$addResize(r => { if (this.Chat) this.Chat.resize(); });