diff --git a/src/hooks/common/echarts.ts b/src/hooks/common/echarts.ts index 73306834..3ecfee87 100644 --- a/src/hooks/common/echarts.ts +++ b/src/hooks/common/echarts.ts @@ -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 * as echarts from 'echarts/core'; import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts'; @@ -86,11 +86,11 @@ export function useEcharts(optionsFactory: () => T, hooks: C const themeStore = useThemeStore(); const darkMode = computed(() => themeStore.darkMode); - const domRef = ref(null); + const domRef = shallowRef(null); const initialSize = { width: 0, height: 0 }; const { width, height } = useElementSize(domRef, initialSize); - let chart: echarts.ECharts | null = null; + const chart = shallowRef(null); const chartOptions: T = optionsFactory(); const { @@ -111,15 +111,6 @@ export function useEcharts(optionsFactory: () => T, hooks: C onDestroy } = 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 */ function isRendered() { return Boolean(domRef.value && chart); @@ -138,52 +129,52 @@ export function useEcharts(optionsFactory: () => T, hooks: C Object.assign(chartOptions, updatedOpts); 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) { - chart?.setOption(options); + chart.value?.setOption(options); } /** render chart */ async function render() { - if (!isRendered()) { - const chartTheme = darkMode.value ? 'dark' : 'light'; + if (isRendered()) return; - 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 */ function resize() { - chart?.resize(); + chart.value?.resize(); } /** destroy chart */ async function destroy() { - if (!chart) return; + if (!chart.value) return; - await onDestroy?.(chart); - chart?.dispose(); - chart = null; + await onDestroy?.(chart.value); + chart.value?.dispose(); + chart.value = null; } /** change chart theme */ async function changeTheme() { await destroy(); await render(); - await onUpdated?.(chart!); + await onUpdated?.(chart.value!); } /** @@ -196,13 +187,6 @@ export function useEcharts(optionsFactory: () => T, hooks: C initialSize.width = w; initialSize.height = h; - // size is abnormal, destroy chart - if (!canRender()) { - await destroy(); - - return; - } - // resize chart if (isRendered()) { resize(); @@ -211,15 +195,17 @@ export function useEcharts(optionsFactory: () => T, hooks: C // render chart await render(); - if (chart) { - await onUpdated?.(chart); - } + await onUpdated?.(chart.value!); } scope.run(() => { - watch([width, height], ([newWidth, newHeight]) => { - renderChartBySize(newWidth, newHeight); - }); + watch( + [width, height], + ([newWidth, newHeight]) => { + renderChartBySize(newWidth, newHeight); + }, + { flush: 'post' } + ); watch(darkMode, () => { changeTheme(); @@ -233,6 +219,7 @@ export function useEcharts(optionsFactory: () => T, hooks: C return { domRef, + chart, updateOptions, setOptions };