在 vue 項目使用 echarts 的場景中,如下三點不容忽視:1. 可視化的數據每每是異步加載的;2. 若一個頁面存在大量的圖表( 尤爲當存在關係圖和地圖時 ),每每會致使該頁面的渲染速度很慢並可能在幾秒內卡死,產生極差的用戶體驗。3. 引入 echarts 組件致使編譯後的文件過大從而使得首次訪問的加載極慢。關於第三點,你們能夠參考以前的撰文 優化 Vue 項目編譯文件大小。如下針對上述前兩點,給出數據異步、延遲渲染的 echarts vue 組件的設計和實現方式,並對實現之中可能存在的問題進行介紹。
首先,咱們須要把 echarts 使用中公共的部分抽離出來,造成基礎組件。html
讓咱們在 官網 - 5 分鐘上手 ECharts 教程中找到使用 echarts 的步驟:vue
# 1. 獲取一個用於掛在 echarts 的 DOM 元素 let $echartsDOM = document.getElementById('echarts-dom') # 2. 初始化 let myEcharts = echarts.init($echartsDOM) # 3. 設置配置項 let option = {...} # 4. 爲 echarts 指定配置 myEcharts.setOption(option)
由上可知,在 echarts 使用中,除第三步設置配置項之外,其餘的步驟都是重複的,便可以抽離出來放入組件中統一實現。編程
首先咱們書寫一個簡單 ehcart.vue
,其中,配置項直接複製於官網的教程示例。segmentfault
<style scoped> .echarts { width: 100%; height: 100%; } </style> <template> <div> <div class="echarts" id="echarts-dom"></div> </div> </template> <script> import echarts from 'echarts' export default { name: 'echarts', data() { return {} }, mounted() { let $echartsDOM = document.getElementById('echarts-dom') let myEcharts = echarts.init($echartsDOM) let option = { title: { text: 'ECharts 入門示例' }, tooltip: {}, legend: { data: ['銷量'] }, xAxis: { data: ["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"] }, yAxis: {}, series: [{ name: '銷量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] } myEcharts.setOption(option) } } </script>
而後在App.vue
中引入這一組件,並設置 echarts 的寬高:api
<style> .echarts-container{ width: 100%; height: 20rem; } </style> <template> <div id="app"> <i-echart class="echarts-container"></i-echart> </div> </template> <script> import iEchart from './components/echart' export default { name: 'app', components: { iEchart } } </script>
刷新頁面後,便可看到柱狀圖。數組
因爲咱們須要抽離 option 部分,最好的方式是將其做爲組件的屬性,即 props 交由調用方配置:app
# echart.vue import echarts from 'echarts' export default { name: 'echarts', props: { option: { type: Object, default(){ return {} } } }, data() { return {} }, mounted() { let $echartsDOM = document.getElementById('echarts-dom') let myEcharts = echarts.init($echartsDOM) let option = this.option myEcharts.setOption(option) } }
而後咱們能夠將 option 配置抽離到組件調用方,並經過「傳參」的方式進行調用:echarts
<i-echart :option="option" class="echarts-container"></i-echart>
以前咱們注意到,在 option 參數中,咱們給出了默認值 {},即空對象。這樣作實際上是有問題的,即在 echarts 中,若是傳入的 option 配置對象不含有 series 鍵,就會拋出錯誤:dom
Error: Option should contains series.
默認值處理是須要存在的,即當調用方傳入的對象爲空或不存在 series 配置時,應在頁面上顯示一些提示( 對用戶友好的提示,而不是對編程人員 ),即避免因報錯而形成空白的狀況。異步
此外,當咱們像以前那樣給 option 這一參數進行類型限制後,假若調用方傳入非對象類型,Vue 會直接拋出錯誤——這一結果也不是咱們想要的。咱們應該取消類型限制,並在 option 發生變化時進行依次如下判斷:
1. 是否爲對象; 2. 是否爲空對象; 3. 是否包含 series 鍵; 4. series 是否爲數組; 5. series 數組是否爲空。
代碼實現以下:
function isValidOption(option){ return isObject(option) && !isEmptyObject(option) && hasSeriesKey(option) && isSeriesArray(option) && !isSeriesEmpty(option) } function isObject(option) { return Object.prototype.isPrototypeOf(option) } function isEmptyObject(option){ return Object.keys(option).length === 0 } function hasSeriesKey(option){ return !!option['series'] } function isSeriesArray(option) { return Array.isArray(option['series']) } function isSeriesEmpty(option){ return option['series'].length === 0 }
而後,當判斷 option 符合上述三種狀況時,在頁面上顯示如「數據爲空」之類的提示:
import echarts from 'echarts' export default { name: 'echarts', props: { option: { default(){ return {} } } }, data() { return { } }, mounted() { //# 1. 獲取一個用於掛在 echarts 的 DOM 元素 let $echartsDOM = document.getElementById('echarts-dom') //# 2. 初始化 let myEcharts = echarts.init($echartsDOM) //# 3. 設置配置項 let option = {...} //# 4. 爲 echarts 指定配置 myEcharts.setOption(option) this.myEcharts = myEcharts this.checkAndSetOption() }, watch: { option(option){ this.checkAndSetOption() } }, methods: { checkAndSetOption(){ let option = this.option //配置等於父組件傳過來的數據 if(isValidOption(option)){ this.myEcharts.setOption(option); //渲染出來 this.myEcharts.hideLoading(); //隱藏加載動畫 }else{ this.myEcharts.showLoading(); //加載動畫 } } } }
這裏在書寫代碼時,有如下幾點須要注意:
document.getElementById()
的返回結果爲空,不能直接使用 echarts.init()
,不然會拋出錯誤:Error: Initialize failed: invalid dom
;immediate: true
使得 watch
鉤子可以在屬性初始化賦值時被觸發,但這樣作是不合適的。由於這樣設置以後,在 option 初始化從而觸發 watch 時,用於掛載 echarts 的 DOM 元素還未存在於頁面中,從而致使出現 TypeError: Cannot read property 'setOption' of null
的錯誤。咱們要重點注意 echarts 做用的生命週期,這一點後續還會涉及。在實際場景中,用於渲染的數據經常是異步獲取的,在異步加載數據之中,咱們可能須要在頁面中顯示如「正在加載...」的字樣來表示加載過程正在進行以提升用戶體驗。而加載過程就組件而言是沒法直接獲取的,因此,咱們須要使用某一參數用於進行加載信息的顯示
ECharts 默認有提供了一個簡單的加載動畫。只須要調用 showLoading 方法顯示。數據加載完成後再調用 hideLoading 方法隱藏加載動畫。
//在App.vue中模擬3秒後獲取數據 data() { return { option: {} } }, created(){ setTimeout(()=>{ this.option={ title: { text: 'ECharts 入門示例' }, tooltip: {}, legend: { data: ['銷量'] }, xAxis: { data: ["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"] }, yAxis: {}, series: [{ name: '銷量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] } console.log(this.option); },3000) }
而後就能夠在echarts組件裏調用了
methods: { checkAndSetOption(){ let option = this.option //配置等於父組件傳過來的數據 if(isValidOption(option)){ this.myEcharts.setOption(option); //渲染出來 this.myEcharts.hideLoading(); //隱藏加載動畫 }else{ this.myEcharts.showLoading(); //加載動畫 } } }
當傳入的 option 值不符合規定時。基於這一標識,咱們能夠對 echarts 組件進行優化,當 option 不合法或數據爲空時給出提示信息而不是顯示空白甚至報錯。