作一個可複用的 echarts-vue 組件(延遲動畫加載)

在 vue 項目使用 echarts 的場景中,如下三點不容忽視:1. 可視化的數據每每是異步加載的;2. 若一個頁面存在大量的圖表( 尤爲當存在關係圖和地圖時 ),每每會致使該頁面的渲染速度很慢並可能在幾秒內卡死,產生極差的用戶體驗。3. 引入 echarts 組件致使編譯後的文件過大從而使得首次訪問的加載極慢。關於第三點,你們能夠參考以前的撰文  優化 Vue 項目編譯文件大小。如下針對上述前兩點,給出數據異步、延遲渲染的 echarts vue 組件的設計和實現方式,並對實現之中可能存在的問題進行介紹。

1. 抽離 echarts 公共部分造成基礎組件


1.1 調研公共部分

首先,咱們須要把 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)
注:在 Vue 中,首先咱們須要使用 import echarts from 'echarts' 以引入 echarts。

由上可知,在 echarts 使用中,除第三步設置配置項之外,其餘的步驟都是重複的,便可以抽離出來放入組件中統一實現。編程

注:其實 option 配置中也存在能夠抽離的部分,好比咱們能夠將 echarts 的顏色、散點大小、折線粗細等提取出來統一賦值,以保證 echarts 風格的統一。但因爲不一樣類型的 ehcarts 圖的顏色配置方式不一樣,於是實現起來相對繁瑣,這裏不進行說明,有興趣的同窗能夠自行嘗試。

1.2 實現 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>

刷新頁面後,便可看到柱狀圖。數組

1.3 組件化

因爲咱們須要抽離 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)
    }
}

1.4 調用組件

而後咱們能夠將 option 配置抽離到組件調用方,並經過「傳參」的方式進行調用:echarts

<i-echart :option="option" class="echarts-container"></i-echart>

1.5 提升組件強壯型

以前咱們注意到,在 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 爲對象後,能夠直接進行第三步的判斷。

而後,當判斷 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();           //加載動畫
            }
        }
    }
}

這裏在書寫代碼時,有如下幾點須要注意:

  • 一、咱們對 DOM 元素獲取結果作了校驗,即當 option 不符合要求時,ID 爲 echarts-dom 的 DOM 元素是不存在的,此時 document.getElementById() 的返回結果爲空,不能直接使用 echarts.init(),不然會拋出錯誤:Error: Initialize failed: invalid dom
  • 二、在 Vue 中,初始化的值不會被 watch 鉤子捕捉,從而致使組件被調用方調用並賦予 option 參數時不會進入校驗。雖然可使用 immediate: true 使得 watch 鉤子可以在屬性初始化賦值時被觸發,但這樣作是不合適的。由於這樣設置以後,在 option 初始化從而觸發 watch 時,用於掛載 echarts 的 DOM 元素還未存在於頁面中,從而致使出現 TypeError: Cannot read property 'setOption' of null 的錯誤。咱們要重點注意 echarts 做用的生命週期,這一點後續還會涉及。

1.6 加強組件功能 - 數據加載提示

在實際場景中,用於渲染的數據經常是異步獲取的,在異步加載數據之中,咱們可能須要在頁面中顯示如「正在加載...」的字樣來表示加載過程正在進行以提升用戶體驗。而加載過程就組件而言是沒法直接獲取的,因此,咱們須要使用某一參數用於進行加載信息的顯示

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();           //加載動畫
        }
    }
}

1.7 加強組件功能 - 數據不合法提示

當傳入的 option 值不符合規定時。基於這一標識,咱們能夠對 echarts 組件進行優化,當 option 不合法或數據爲空時給出提示信息而不是顯示空白甚至報錯。

PS:暫時更新到這了,若是有後續,我回接着更新了

相關文章
相關標籤/搜索