vue3.x对echarts的二次封装之按需加载过程详解

 更新时间:2023年09月13日 09:36:36   作者:SunnyRun!  
echarts是我们后台系统中最常用的数据统计图形展示,外界对它的二次封装也不计层数,这篇文章主要介绍了vue3.x对echarts的二次封装之按需加载,需要的朋友可以参考下

效果展示

在这里插入图片描述

1、echarts是我们后台系统中最常用的数据统计图形展示,外界对它的二次封装也不计层数;
2、在业务代码内每次的初始dom和绑定setOption导致代码量的堆积不利于维护
3、拓展公共echarts组件,通过不同入参开启对应的功能更利于维护和排查问题
4、echarts的版本5.4.x

  • 当前代码示例只引用了:BarChart, LineChart, PieChart, GaugeChart 这几种图形类型,其余类型需按需引用,在useCharts.ts内进行

1. 创建v-charts文件夹;

可自定义文件名

1.1 创建useCharts.ts 文件

该文件用作于处理和初始化echarts的公用逻辑,抽离出来使用vue3的hooks用来注水操作

1.2 创建v-charts.vue 文件

该文件用作于echarts的dom承载和相关api的入参只有少量逻辑;

2. 相关代码的处理方式:

useCharts.ts文件

import * as echarts from 'echarts/core'
import {
  TitleComponent,
  LegendComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  ToolboxComponent,
  MarkAreaComponent,
  MarkLineComponent,
  MarkPointComponent
} from 'echarts/components'
import { BarChart, LineChart, PieChart, GaugeChart } from 'echarts/charts'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import { ShallowRef, shallowRef, Ref, onBeforeUnmount, watch, useAttrs, shallowReactive } from 'vue'
interface ChartHookOption {
  theme?: Ref<string>
  el: ShallowRef<HTMLElement>
  options: any
}
/**
 *  视口变化时echart图表自适应调整
 */
class ChartsResize {
  #charts = new Set<echarts.ECharts>() // 缓存已经创建的图表实例
  #timeId = null
  constructor() {
    window.addEventListener('resize', this.handleResize.bind(this)) // 视口变化时调整图表
  }
  getCharts() {
    return [...this.#charts]
  }
  handleResize() {
    clearTimeout(this.#timeId)
    this.#timeId = setTimeout(() => {
      this.#charts.forEach((chart) => {
        chart.resize()
      })
    }, 350)
  }
  add(chart: echarts.ECharts) {
    this.#charts.add(chart)
  }
  remove(chart: echarts.ECharts) {
    this.#charts.delete(chart)
  }
  removeListener() {
    window.removeEventListener('resize', this.handleResize)
  }
}
export const chartsResize = new ChartsResize()
export const useCharts = ({ el, theme, options }: ChartHookOption) => {
  echarts.use([
    BarChart,
    LineChart,
    BarChart,
    PieChart,
    GaugeChart,
    TitleComponent,
    LegendComponent,
    TooltipComponent,
    GridComponent,
    DatasetComponent,
    TransformComponent,
    LabelLayout,
    UniversalTransition,
    CanvasRenderer,
    ToolboxComponent,
    MarkAreaComponent,
    MarkLineComponent,
    MarkPointComponent
  ])
  const charts = shallowRef<echarts.ECharts>()
  const setOptions = (opt: echarts.EChartsCoreOption) => {
    charts.value.setOption(opt)
  }
  const initChart = () => {
    charts.value = echarts.init(el.value, theme)
    charts.value.setOption(options)
    chartsResize.add(charts.value) // 将图表实例添加到缓存中
    initEvent() // 添加事件支持
  }
  // 初始化事件
  const attrs = useAttrs()
  const initEvent = () => {
    Object.keys(attrs).forEach((attrKey) => {
      if (/^on/.test(attrKey)) {
        const cb = attrs[attrKey]
        attrKey = attrKey.replace(/^on(Chart)?/, '')
        attrKey = `${attrKey[0]}${attrKey.substring(1)}`
        typeof cb === 'function' && charts.value?.on(attrKey, cb as () => void)
      }
    })
  }
  onBeforeUnmount(() => {
    chartsResize.remove(charts.value) // 移除缓存
  })
  return {
    charts,
    setOptions,
    initChart,
    initEvent
  }
}
export const chartsOptions = <T extends echarts.EChartsCoreOption>(option: T) => shallowReactive<T>(option)

v-charts.vue代码模块

<template>
  <div class="v-charts" ref="chartRef" />
</template>
<script lang="ts" setup>
import * as echarts from 'echarts/core'
import { useCharts, chartsResize } from './useCharts'
import { PropType, toRefs, shallowRef, onMounted, watch, nextTick } from 'vue'
const props = defineProps({
  theme: String,
  delay: [String, Boolean],
  isWatch: [String, Boolean, Object],
  options: {
    type: Object as PropType<echarts.EChartsCoreOption>,
    default: () => ({})
  },
})
const { theme, options } = toRefs(props)
const chartRef = shallowRef()
const { charts, setOptions, initChart } = useCharts({ theme, el: chartRef, options })
// 开启默认放大缩放功能
const turnOndataZoom = () => {
  charts.value.dispatchAction({
    type: 'takeGlobalCursor',
    key: 'dataZoomSelect',
    dataZoomSelectActive: true
  })
}
onMounted(async () => {
  await initChart()
  setOptions(options.value)
})
watch(
  options,
  () => {
    setOptions(options.value)
    nextTick(() => turnOndataZoom())
  },
  {
    deep: true
  }
)
watch(
  () => props.isWatch, // 是否开启外部左侧菜单引起的布局适配问题
  () => {
    chartsResize.handleResize()
  },
  {
    deep: true,
    immediate: true
  }
)
defineExpose({
  chartRef: chartRef,
  $charts: charts
})
</script>
<script lang="ts">
export default { name: "v-charts" };
</script>
<style lang="scss" scoped>
.v-charts {
  width: 100%;
  height: 100%;
  clear: both;
  min-height: 360px;
}
</style>

3、引用组件或者全局注入

3.1 创建index.js文件

import vCharts from './v-charts/v-charts.vue'
export * from './v-charts/useCharts';
const components = [vCharts]; // 可添加需要全局注入的公共组件
const install = function (Vue: any) {
  components.forEach((app) => {
    Vue.component(app.name, app);
  });
};
export default install;

3.2 在main.ts文件内进行引用

import CustomUi from '@/components/index'
app.use(CustomUi)

4、在业务文件中的使用

<template>
	<v-charts ref="myCharts" :isWatch="isActiveName" :options="setOptions" />
</template>
<script lang="ts" setup>
import { ref, reactive, shallowRef, onBeforeMount } from 'vue'
const option = {
  toolbox: {
    feature: {
      dataZoom: {
        icon: null
      }
    }
  },
  xAxis: {
    data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  },
  yAxis: {},
  series: [
    {
      type: "line",
      data: [23, 24, 18, 25, 27, 28, 25],
    },
  ],
};
const myCharts = ref(null)
const isActiveName = ref<boolean>(false)
const setOptions = shallowRef<Record<string, any>>({})
onBeforeMount(() => {
  setOptions.value = option
})
</script>

5、完结

第一版的时候setOption这块的内容是在组件内部;因为我们的业务偏复杂,操作setOption内容较多又涉及到轮询处理数据结构;所以将该内容放置外了;这块可以依据自身需求而定
封装echarts没有过于封装,主要是针对按需情况和初始化绑定,自适应屏幕而定的封装
不通的需求处理方式不通,有不合理之处还请各位谅解

到此这篇关于vue3.x对echarts的二次封装之按需加载的文章就介绍到这了,更多相关vue3.x按需加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue 兄弟组件的信息传递的方法实例详解

    vue 兄弟组件的信息传递的方法实例详解

    这篇文章主要介绍了vue 兄弟组件的信息传递的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • vue 框架下自定义滚动条(easyscroll)实现方法

    vue 框架下自定义滚动条(easyscroll)实现方法

    这篇文章主要介绍了vue 框架下自定义滚动条(easyscroll)实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 详解Vue用axios发送post请求自动set cookie

    详解Vue用axios发送post请求自动set cookie

    本篇文章主要介绍了Vue用axios发送post请求自动set cookie,非常具有实用价值,需要的朋友可以参考下
    2017-05-05
  • vue中如何实时监听本地存储

    vue中如何实时监听本地存储

    这篇文章主要介绍了vue中如何实时监听本地存储,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • Vue CompositionAPI中watch和watchEffect的区别详解

    Vue CompositionAPI中watch和watchEffect的区别详解

    这篇文章主要为大家详细介绍了Vue CompositionAPI中watch和watchEffect的区别,文中的示例代码简洁易懂,希望对大家学习Vue有一定的帮助
    2023-06-06
  • vue项目中使用scss详细方法步骤

    vue项目中使用scss详细方法步骤

    这篇文章主要给大家介绍了关于vue项目中使用scss的详细方法步骤,scss是一种css预处理语言,定义了一种新的专门的编程语言,编译后形成正常的css文件,为css增加一些编程特性,无需考虑浏览器的兼容性,让css更加简洁、适应性更强,可读性更佳,需要的朋友可以参考下
    2023-11-11
  • vue实现监听数值的变化,并捕捉到

    vue实现监听数值的变化,并捕捉到

    这篇文章主要介绍了vue实现监听数值的变化,并捕捉到问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Vue slot插槽作用与原理深入讲解

    Vue slot插槽作用与原理深入讲解

    插槽slot可以说在一个Vue项目里面处处都有它的身影,比如我们使用一些UI组件库的时候,我们通常可以使用插槽来自定义我们的内容,这篇文章主要介绍了Vue3中slot插槽使用方式,需要的朋友可以参考下
    2023-01-01
  • Vue无法访问.env.development定义的变量值问题及解决

    Vue无法访问.env.development定义的变量值问题及解决

    这篇文章主要介绍了Vue无法访问.env.development定义的变量值问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Vue之vue.$set()方法源码案例详解

    Vue之vue.$set()方法源码案例详解

    这篇文章主要介绍了Vue之vue.$set()方法源码案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08

最新评论