关于vue3:vue3-ts-echarts封装一个基础echarts组件

8次阅读

共计 2195 个字符,预计需要花费 6 分钟才能阅读完成。

话不多说,间接上代码吧

新增一个 MyCharts.vue 文件, 文件内容如下

<!--
/**
* Author: 前端小高
* Desc: MyCharts 图表组件
*/
-->

<template>
  <div :id="chartId" :style="getChartStyle"></div>
</template>

<script name="MyCharts" lang="ts" setup>
import {
  ref,
  shallowRef,
  computed,
  watch,
  onMounted,
  onBeforeUnmount,
  getCurrentInstance,
  PropType
} from 'vue'
import {debounce} from 'lodash'
const {proxy} = getCurrentInstance() as any

const props = defineProps({
  options: {
    type: Object,
    default: () => {return {}
    }
  },
  height: {
    type: Number,
    default: 300
  },
  // 是否不跟之前的传入值合并
  notMerge: {
    type: Boolean,
    default: true
  }
})

const getChartStyle = computed(() => {
  return {
    width: '100%',
    height: `${props.height}px`
  }
})

watch(() => props.options,
  () => {initChart()
  },
  {deep: true}
)

// 默认显示的图表配置数据
const defaultOptions = {
  tooltip: {trigger: 'axis'},
  legend: {data: ['Email', 'Union Ads']
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {type: 'value'},
  series: [
    {
      name: 'Email',
      type: 'line',
      smooth: true,
      stack: 'Total',
      data: [120, 132, 101, 134, 90, 230, 210]
    },
    {
      name: 'Union Ads',
      type: 'line',
      smooth: true,
      stack: 'Total',
      data: [220, 182, 191, 234, 290, 330, 310]
    }
  ]
}

const getRandomStr = () => {const randomNumStr = String(Math.random()).split('.')[1]
  return randomNumStr
}

const chartId = ref('chart-id')
const getChartId = () => {const str = 'chart-id-' + getRandomStr()
  chartId.value = str
}

getChartId()

const resizeHandler = () => {eChartsRef.value.resize()
}

const resizeHandlerOrigin = debounce(resizeHandler, 500)

const eCharts = proxy.$ECharts
const eChartsRef = shallowRef<any>()
const initChart = () => {eChartsRef.value = eCharts.init(document.getElementById(chartId.value))
  let options = {}
  if (isEmptyObj(props.options)) {options = defaultOptions} else {options = props.options}
  eChartsRef.value.setOption(options, props.notMerge)
  window.addEventListener('resize', resizeHandlerOrigin)
}

const isEmptyObj = (obj) => {return typeof obj === 'object' && JSON.stringify(obj) === '{}'}

onMounted(() => {initChart()
})

onBeforeUnmount(() => {window.removeEventListener('resize', resizeHandlerOrigin)
  eChartsRef.value.dispose()})

watch(() => props.options,
  () => {initChart()
  },
  {deep: true}
)
</script>
<style lang="scss" scoped></style>

页面下援用组件及应用办法

<template>
    <my-charts></my-charts>
</template>

<script name="TestPage" lang="ts" setup>
    import MyCharts from  './MyCharts.vue'
</script>

预览成果如下

正文完
 0