基于echarts封装通用图表组件

146 阅读2分钟

Vue3 + echarts 图表组件

图表组件

  1. 传入options自动生成图表
  2. 传入width,height 可配置图表大小
  3. 窗口改变,图表大小自适应
  4. options 改表时,重新生成图表
<MyEcharts :options="options" width="50%" height="300px"/>

MyECharts.vue

<template>
    <div>
        <div :id="uuid" :style="style"></div>
    </div>
</template>

<script lang='ts' setup>
import * as echarts from 'echarts'
import { debounce, throttle } from 'lodash';
import { ref, defineProps, watch, computed, onBeforeMount, onMounted, shallowRef, onBeforeUnmount } from 'vue'
const props = defineProps({
    // 图表高度
    height: {
      type: String,
      default: '200px',
    },
    // 图标宽度
    width: {
      type: String,
      default: '700px',
    },
    // 配置项
    options: {
      type: Object,
      default: null,
    },
})
const uuid = ref(null)
let myChart = shallowRef(null)
watch(() => props.options,
    (newVal, oldVal) => {
        console.log('options newVal',newVal);
        changeData()
    }, 
    {deep: true}
)
const style = computed(()=>{
    // 当宽高变化时,重新计算echarts图表style样式
    return {
        height: props.height,
        width: props.width,
    }
})
const changeData = () =>{
      myChart.value.clear()
      myChart.value.setOption(props.options, true, true) //第一个true表示noMerge,第二个true表示lazyUpdata
}
const changeStyle = debounce(() => {
    console.log('changeStyle');
    myChart.value.resize()
},100)
const guid = () => {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c,) {
        let r = (Math.random() * 16) | 0,
            v = c == 'x' ? r : (r & 0x3) | 0x8
        return v.toString(16)
    })
}     
onBeforeMount(()=>{
    console.log('onBeforeMount');
    uuid.value = guid() // "a1ca0f7b-51bd-4bf3-a5d5-6a74f6adc1c7"
    console.log(uuid.value);
})
let observer = ref(null)
onMounted(()=>{
    console.log('onMounted');
    myChart.value = echarts.init(document.getElementById(uuid.value))
    myChart.value.setOption(props.options) //第一个true表示noMerge,第二个true表示lazyUpdata
    window.addEventListener('resize', changeStyle)
})  
onBeforeUnmount(() => {
    console.log('onBeforeUnmount');
    window.removeEventListener('resize', changeStyle)
})
</script>

<style scoped lang="scss">

</style>

支持svg渲染

echarts默认使用canvas渲染,可以设置使用svg渲染图表

注意: SVG暂不支持 富文本、材质、炫光尾迹特效、带有混合效果的热力图

myChart.value = echarts.init(document.getElementById(uuid.value),null,{renderer:'svg'})

Vue2 echarts 图表组件

  1. 只需传入 options,width,heigth
  2. 支持宽高自适应
  3. 支持 options 改变图表自动更新
<MyEcharts :options="options" width="50%" height="300px"/>

MyECharts.vue

<template>
  <div :id="uuid" :style="style"></div>
</template>

<script>
import * as echarts from 'echarts'
import { debounce, throttle } from 'lodash';
export default {
  props: {
    // 图表高度
    height: {
      type: String,
      default: '200px',
    },
    // 图标宽度
    width: {
      type: String,
      default: '700px',
    },
    // 配置项
    options: {
      type: Object,
      default: null,
    },
  },
  data() {
    return {
      uuid: null, //唯一标识echarts图表实例,id不能重复
      myChart: null, //将创建的echarts实例被data管理(也就是被vue管理)
    }
  },
  watch: {
    width() {
      // 监听width改变,width改变时重置echarts实例
      if (this.myChart) {
        this.changeStyle() // 重置echarts实例大小
      }
    },
    options: {
      // 监听options改变,options改变时重置echarts实例
      handler() {
        this.changeData()
      },
      deep: true,
    },
  },
  computed: {
    style() {
      // 当宽高变化时,重新计算echarts图表style样式
      return {
        height: this.height,
        width: this.width,
      }
    },
  },
  methods: {
    changeStyle() {
      debounce(this.myChart.resize(),100)
    },
    changeData() {
      this.myChart.clear()
      this.myChart.setOption(this.options, true, true) //第一个true表示noMerge,第二个true表示lazyUpdata
    },
  },
  created() {
    function guid() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (
        c,
      ) {
        let r = (Math.random() * 16) | 0,
          v = c == 'x' ? r : (r & 0x3) | 0x8
        return v.toString(16)
      })
    }
    this.uuid = guid() // "a1ca0f7b-51bd-4bf3-a5d5-6a74f6adc1c7"
  },
  mounted() {
    // 准备实例
    this.myChart = echarts.init(document.getElementById(this.uuid))
    // 使用配置项
    this.myChart.setOption(this.options)
    window.addEventListener('resize',changeStyle)
  },
  beforeDestroy() {
    window.removeEventListener('resize',changeStyle)
  },
}
</script>

<style></style>