optimize(hooks): optimize useEcharts

This commit is contained in:
Soybean 2025-07-19 02:53:46 +08:00
parent c965140b87
commit 936b834e62

View File

@ -1,4 +1,4 @@
import { computed, effectScope, nextTick, onScopeDispose, ref, watch } from 'vue'; import { computed, effectScope, nextTick, onScopeDispose, shallowRef, watch } from 'vue';
import { useElementSize } from '@vueuse/core'; import { useElementSize } from '@vueuse/core';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts'; import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts';
@ -86,11 +86,11 @@ export function useEcharts<T extends ECOption>(optionsFactory: () => T, hooks: C
const themeStore = useThemeStore(); const themeStore = useThemeStore();
const darkMode = computed(() => themeStore.darkMode); const darkMode = computed(() => themeStore.darkMode);
const domRef = ref<HTMLElement | null>(null); const domRef = shallowRef<HTMLElement | null>(null);
const initialSize = { width: 0, height: 0 }; const initialSize = { width: 0, height: 0 };
const { width, height } = useElementSize(domRef, initialSize); const { width, height } = useElementSize(domRef, initialSize);
let chart: echarts.ECharts | null = null; const chart = shallowRef<echarts.ECharts | null>(null);
const chartOptions: T = optionsFactory(); const chartOptions: T = optionsFactory();
const { const {
@ -111,15 +111,6 @@ export function useEcharts<T extends ECOption>(optionsFactory: () => T, hooks: C
onDestroy onDestroy
} = hooks; } = hooks;
/**
* whether can render chart
*
* when domRef is ready and initialSize is valid
*/
function canRender() {
return domRef.value && initialSize.width > 0 && initialSize.height > 0;
}
/** is chart rendered */ /** is chart rendered */
function isRendered() { function isRendered() {
return Boolean(domRef.value && chart); return Boolean(domRef.value && chart);
@ -138,52 +129,52 @@ export function useEcharts<T extends ECOption>(optionsFactory: () => T, hooks: C
Object.assign(chartOptions, updatedOpts); Object.assign(chartOptions, updatedOpts);
if (isRendered()) { if (isRendered()) {
chart?.clear(); chart.value?.clear();
} }
chart?.setOption({ ...updatedOpts, backgroundColor: 'transparent' }); chart.value?.setOption({ ...updatedOpts, backgroundColor: 'transparent' });
await onUpdated?.(chart!); await onUpdated?.(chart.value!);
} }
function setOptions(options: T) { function setOptions(options: T) {
chart?.setOption(options); chart.value?.setOption(options);
} }
/** render chart */ /** render chart */
async function render() { async function render() {
if (!isRendered()) { if (isRendered()) return;
const chartTheme = darkMode.value ? 'dark' : 'light';
await nextTick(); const chartTheme = darkMode.value ? 'dark' : 'light';
chart = echarts.init(domRef.value, chartTheme); await nextTick();
chart.setOption({ ...chartOptions, backgroundColor: 'transparent' }); chart.value = echarts.init(domRef.value, chartTheme);
await onRender?.(chart); chart.value?.setOption({ ...chartOptions, backgroundColor: 'transparent' });
}
await onRender?.(chart.value!);
} }
/** resize chart */ /** resize chart */
function resize() { function resize() {
chart?.resize(); chart.value?.resize();
} }
/** destroy chart */ /** destroy chart */
async function destroy() { async function destroy() {
if (!chart) return; if (!chart.value) return;
await onDestroy?.(chart); await onDestroy?.(chart.value);
chart?.dispose(); chart.value?.dispose();
chart = null; chart.value = null;
} }
/** change chart theme */ /** change chart theme */
async function changeTheme() { async function changeTheme() {
await destroy(); await destroy();
await render(); await render();
await onUpdated?.(chart!); await onUpdated?.(chart.value!);
} }
/** /**
@ -196,13 +187,6 @@ export function useEcharts<T extends ECOption>(optionsFactory: () => T, hooks: C
initialSize.width = w; initialSize.width = w;
initialSize.height = h; initialSize.height = h;
// size is abnormal, destroy chart
if (!canRender()) {
await destroy();
return;
}
// resize chart // resize chart
if (isRendered()) { if (isRendered()) {
resize(); resize();
@ -211,15 +195,17 @@ export function useEcharts<T extends ECOption>(optionsFactory: () => T, hooks: C
// render chart // render chart
await render(); await render();
if (chart) { await onUpdated?.(chart.value!);
await onUpdated?.(chart);
}
} }
scope.run(() => { scope.run(() => {
watch([width, height], ([newWidth, newHeight]) => { watch(
renderChartBySize(newWidth, newHeight); [width, height],
}); ([newWidth, newHeight]) => {
renderChartBySize(newWidth, newHeight);
},
{ flush: 'post' }
);
watch(darkMode, () => { watch(darkMode, () => {
changeTheme(); changeTheme();
@ -233,6 +219,7 @@ export function useEcharts<T extends ECOption>(optionsFactory: () => T, hooks: C
return { return {
domRef, domRef,
chart,
updateOptions, updateOptions,
setOptions setOptions
}; };