vue3.x對echarts的二次封裝之按需加載過程詳解
效果展示
1、echarts是我們后臺系統(tǒng)中最常用的數(shù)據(jù)統(tǒng)計圖形展示,外界對它的二次封裝也不計層數(shù);
2、在業(yè)務(wù)代碼內(nèi)每次的初始dom和綁定setOption導(dǎo)致代碼量的堆積不利于維護(hù)
3、拓展公共echarts組件,通過不同入?yún)㈤_啟對應(yīng)的功能更利于維護(hù)和排查問題
4、echarts的版本5.4.x
- 當(dāng)前代碼示例只引用了:BarChart, LineChart, PieChart, GaugeChart 這幾種圖形類型,其余類型需按需引用,在useCharts.ts內(nèi)進(jìn)行
1. 創(chuàng)建v-charts文件夾;
可自定義文件名
1.1 創(chuàng)建useCharts.ts 文件
該文件用作于處理和初始化echarts的公用邏輯,抽離出來使用vue3的hooks用來注水操作
1.2 創(chuàng)建v-charts.vue 文件
該文件用作于echarts的dom承載和相關(guān)api的入?yún)⒅挥猩倭窟壿嫞?/p>
2. 相關(guān)代碼的處理方式:
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圖表自適應(yīng)調(diào)整 */ class ChartsResize { #charts = new Set<echarts.ECharts>() // 緩存已經(jīng)創(chuàng)建的圖表實(shí)例 #timeId = null constructor() { window.addEventListener('resize', this.handleResize.bind(this)) // 視口變化時調(diào)整圖表 } 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) // 將圖表實(shí)例添加到緩存中 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 }) // 開啟默認(rèn)放大縮放功能 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, // 是否開啟外部左側(cè)菜單引起的布局適配問題 () => { 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 創(chuàng)建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文件內(nèi)進(jìn)行引用
import CustomUi from '@/components/index' app.use(CustomUi)
4、在業(yè)務(wù)文件中的使用
<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、完結(jié)
第一版的時候setOption這塊的內(nèi)容是在組件內(nèi)部;因?yàn)槲覀兊臉I(yè)務(wù)偏復(fù)雜,操作setOption內(nèi)容較多又涉及到輪詢處理數(shù)據(jù)結(jié)構(gòu);所以將該內(nèi)容放置外了;這塊可以依據(jù)自身需求而定
封裝echarts沒有過于封裝,主要是針對按需情況和初始化綁定,自適應(yīng)屏幕而定的封裝
不通的需求處理方式不通,有不合理之處還請各位諒解
到此這篇關(guān)于vue3.x對echarts的二次封裝之按需加載的文章就介紹到這了,更多相關(guān)vue3.x按需加載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue或者React項(xiàng)目配置@路徑別名及智能提示方案
這篇文章主要介紹了Vue或者React項(xiàng)目配置@路徑別名及智能提示方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10Vue3使用customRef封裝防抖函數(shù)的方法詳解
防抖函數(shù)的作用是高頻率觸發(fā)的事件,在指定的單位時間內(nèi),只響應(yīng)最后一次,如果在指定的時間內(nèi)再次觸發(fā),則重新計算時間,本文將給大家詳細(xì)的介紹一下Vue3使用customRef封裝防抖函數(shù)的方法,需要的朋友可以參考下2023-09-09Vue Router實(shí)現(xiàn)多層嵌套路由的導(dǎo)航的詳細(xì)指南
在 Vue 應(yīng)用中,使用 Vue Router 可以輕松實(shí)現(xiàn)多層嵌套路由的導(dǎo)航,嵌套路由允許你創(chuàng)建一個多層次的 URL 結(jié)構(gòu),這在構(gòu)建具有復(fù)雜導(dǎo)航結(jié)構(gòu)的應(yīng)用程序時非常有用,需要的朋友可以參考下2024-10-10vue 實(shí)現(xiàn)搜索的結(jié)果頁面支持全選與取消全選功能
這篇文章主要介紹了vue 實(shí)現(xiàn)搜索的結(jié)果頁面支持全選與取消全選功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05vue3?使用provide?inject父子組件傳值失敗且子組件不響應(yīng)
這篇文章主要介紹了vue3使用provide?inject父子組件傳值傳不過去且傳遞后子組件不具備響應(yīng)性問題解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08el-date-picker日期范圍限制的實(shí)現(xiàn)
本文主要介紹了el-date-picker日期范圍限制的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05