Vue + Element-ui實現後臺管理系統(4)---封裝一個ECharts組件的一點思路

封裝一個ECharts組件的一點思路

有關後臺管理系統以前寫過三遍博客,看這篇以前最好先看下這三篇博客。另外這裏只展現關鍵部分代碼,項目代碼放在github上: mall-manage-systemjavascript

一、Vue + Element-ui實現後臺管理系統(1) --- 總述css

二、Vue + Element-ui實現後臺管理系統(2) --- 項目搭建 + ⾸⻚佈局實現html

三、Vue + Element-ui實現後臺管理系統(3) --- 麪包屑 + Tag標籤切換功能vue

這篇主要講解實現圖表的功能:java

總體效果git

1、封裝一個ECharts組件的一點思路

一、繪製一個簡單的圖表

ECharts上手很是簡單,具體簡單示例能夠參考我以前寫的一篇博客:圖表工具--- ECharts.js學習(一) 簡單入門github

二、封裝思路

在實際項目開發中,咱們會常常與圖表打交道,好比 訂單數量表商品銷量表會員數量表等等,它多是以折線圖柱狀圖餅狀圖等等的方式來展示。小程序

若是咱們沒有封裝組件的思想的話,那麼咱們每次須要畫一個圖表都要重複相似相同的工做,並且代碼看去很是冗餘。因此咱們就須要考慮封裝一個ECharts組件,這個組件經過接收echarts

不一樣的數據來渲染成不一樣的圖表,之後當須要生成一張圖表的時候,只須要把相關的數據傳入到這個組件中,就會渲染對應的圖表。ide

而這裏的核心就是 哪些數據是須要咱們傳入組件中的。針對這個問題咱們來看下一個ECharts最簡單的示例

// 指定圖表的配置項和數據
        var option = {
            title: {
                text: 'ECharts 入門示例'
            },
            tooltip: {},
            legend: {
                data:['銷量']
            },
            xAxis: {
                data: ["襯衫","羊毛衫","雪紡衫","褲子","高跟鞋","襪子"]
            },
            yAxis: {},
            series: [{
                name: '銷量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        };

運行結果

這裏展現了一個最簡單的圖表,官方例子地址:5 分鐘上手 ECharts,下面對這些參數作個講解

title : 標題

tooltip : 提示框組件

legend : 圖例組件

xAxis : 直角座標軸中的 x 軸

yAxis : 直角座標軸中的 y 軸

series : 系列列表。每一個系列經過 type 決定本身的圖表類型

這幾個組件來看 seriesxAxis 是確定須要外部傳來的數據,y軸 的數據跟series中data相關不須要單獨再傳。至於title , tooltip , legend並非圖表必須的,因此

不是必需要傳的。就比如你一個圖表你能夠沒有標題。

注意 這裏還有一點 x軸對於柱狀圖、折線圖相關圖是必定要有的,但對於餅狀圖來說它又不是必須的,因此這裏封裝一個ECharts組件時,須要考慮這一點。

三、封裝ECharts組件

新建一個EChart.vue,做爲封裝ECharts的組件

<template>
  <!--圖表展現在這個div中-->
  <div style="height: 100%" ref="echart">
    echart
  </div>
</template>

<script>
import echarts from 'echarts'
export default {
  //接收父類兩個數據 一、chartData (series數據 + x座標系數據)二、isAxisChart (是否有x座標系,若是false,那麼上面的xData就爲空)
  props: {
    chartData: {
      type: Object,
      default() {
        return {
          xData: [],
          series: []
        }
      }
    },
    isAxisChart: {
    //默認type爲true 就表明默認是有x軸的
      type: Boolean,
      default: true
    }
  },
  computed: {
    //計算 選擇是有x軸 仍是沒有x軸的數據
    options() {
      return this.isAxisChart ? this.axisOption : this.normalOption
    },
    //用於下面的resize 改變圖表尺寸,在容器大小發生改變時須要手動調用
    isCollapse() {
      return this.$store.state.tab.isCollapse
    }
  },
  watch: {
    //監聽chartData數據
    chartData: {
      handler: function() {
        this.initChart()
      },
      deep: true
    },
    //監聽isCollapse 由於頭部水平擴展是一個動畫須要時間,因此這裏延遲300毫秒
    isCollapse() {
      setTimeout(() => {
        this.resizeChart()
      }, 300)
    }
  },
  data() {
    //在數據中有些數據在數據件中是寫死的
    return {
      echart: null,
      axisOption: {
        legend: {
          textStyle: {
            color: '#333'
          }
        },
        grid: {
          left: '20%'
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          type: 'category',
          data: [],
          axisLine: {
            lineStyle: {
              color: '#17b3a3'
            }
          },
          axisLabel: {
            color: '#333'
          }
        },
        yAxis: [
          {
            type: 'value',
            axisLine: {
              lineStyle: {
                color: '#17b3a3'
              }
            }
          }
        ],
        color: [
          '#2ec7c9',
          '#b6a2de',
          '#5ab1ef',
          '#ffb980',
          '#d87a80',
          '#8d98b3',
          '#e5cf0d',
          '#97b552',
          '#95706d',
          '#dc69aa',
          '#07a2a4',
          '#9a7fd1',
          '#588dd5'
        ],
        series: []
      },
      normalOption: {
        tooltip: {
          trigger: 'item'
        },
        color: ['#0f78f4', '#dd536b', '#9462e5', '#a6a6a6', '#e1bb22', '#39c362', '#3ed1cf'],
        series: []
      }
    }
  },
  methods: {
    initChart() {
      //獲取處理好的數據
      this.initChartData()
      //獲取echart對象
      if (this.echart) {
        this.echart.setOption(this.options)
      } else {
        //經過refs獲取
        this.echart = echarts.init(this.$refs.echart)
        this.echart.setOption(this.options)
      }
    },
    //處理好數據
    initChartData() {
      if (this.isAxisChart) {
        this.axisOption.xAxis.data = this.chartData.xData
        this.axisOption.series = this.chartData.series
      } else {
        this.normalOption.series = this.chartData.series
      }
    },
    resizeChart() {
      this.echart ? this.echart.resize() : ''
    }
  },
  mounted() {
    //resize 改變圖表尺寸,在容器大小發生改變時須要手動調用(由於側邊欄是能夠收縮的,因此這裏圖表根據是否收縮來改變圖表尺寸)
    window.addEventListener('resize', this.resizeChart)
  },
  //銷燬 防止內存泄漏
  destroyed() {
    window.removeEventListener('resize', this.resizeChart)
  }
}
</script>

<style lang="scss" scoped></style>

這樣一個簡單的公共組件就完成了,接下來咱們經過傳入不一樣的數據到這個組件來渲染不一樣的圖表。


2、傳入EChart組件數據

咱們看到在首頁有三個圖表,那咱們這裏就要組裝三種不一樣的數據,傳入到EChart.vue組件中,來生成不一樣的圖表。

<template>
   <div>
       <!--圖表一 這裏的數據是折線圖-->
    <echart style="height: 280px" :chartData="echartData.order"></echart>
       <!--圖表二 這裏的數據是柱狀圖-->
    <echart :chartData="echartData.user" style="height: 260px"></echart>
       <!--圖表三 這裏的數據是餅狀圖 由於餅狀圖是不用x軸的 因此這裏isAxisChart爲false-->
    <echart :chartData="echartData.video" style="height: 260px" :isAxisChart="false"> 
    </div>
</template>

<script>
import Echart from '../../components/EChart'
export default {
  components: {
    Echart
  },
  data() {
    return {
      echartData: {
        //圖一
        order: {
          xData: [],
          series: []
        },
        //圖二
        user: {
          xData: [],
          series: []
        },
        //圖三 餅狀圖沒有x軸
        mall: {
          series: []
        }
      }
    }
  },
  methods: {
    getTableData() {
      this.$http.get('/home/getData').then(res => {
        res = res.data
        // 訂單折線圖
        const order = res.data.orderData
        //x軸數據 爲日前
        this.echartData.order.xData = order.date
        // 第一步取出series中的name部分——小米,三星、蘋果...
        let keyArray = Object.keys(order.data[0])
        // 第二步,循環添加數據
        keyArray.forEach(key => {
          this.echartData.order.series.push({
            //若是有須要還能夠作一步抓換好比:後臺返回性別是一、2。那這裏key === 1 ? '男' : 女,
            name: key === 'wechat' ? '小程序' : key,
            data: order.data.map(item => item[key]),
            type: 'line'
          })
        })
        // 用戶柱狀圖
        this.echartData.user.xData = res.data.userData.map(item => item.date)
        this.echartData.user.series.push({
          name: '新增用戶',
          data: res.data.userData.map(item => item.new),
          type: 'bar'
        })
        this.echartData.user.series.push({
          name: '活躍用戶',
          data: res.data.userData.map(item => item.active),
          type: 'bar',
          barGap: 0
        })
        // 商品餅圖
        this.echartData.mall.series.push({
          data: res.data.mallData,
          type: 'pie'
        })
      })
    }
  },
  created() {
    this.getTableData()
  }
}
</script>

大體的思路就是這樣的,若是你想在組件中加入title等參數,那也能夠修改下這個組件就能夠了。

總結下封裝組件的基本思路

一、觀察⽂檔,考慮組件須要的基本參數
二、參數篩選,分爲從⽗組件傳來的參數和⾃身的參數
三、完善組件,觀察設計圖,找不一樣,在⽂檔中尋找對應的配置項
四、細節優化,考慮多種場景下,圖表⾃適應的處理


別人罵我胖,我會生氣,由於我內心認可了我胖。別人說我矮,我就會以爲可笑,由於我內心知道我不可能矮。這就是咱們爲何會對別人的攻擊生氣。
攻我盾者,乃我心裏之矛(14)
相關文章
相關標籤/搜索