/
chart.ts
117 lines (97 loc) 路 2.69 KB
/
chart.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import {
defineComponent,
ref,
shallowRef,
h,
onMounted,
onBeforeUnmount,
watch,
toRaw
} from 'vue'
import { Chart as ChartJS } from 'chart.js'
import type { ChartComponent } from './types.js'
import { Props } from './props.js'
import {
cloneData,
setLabels,
setDatasets,
setOptions,
toRawIfProxy,
cloneProxy
} from './utils.js'
export const Chart = defineComponent({
props: Props,
setup(props, { expose }) {
const canvasRef = ref<HTMLCanvasElement | null>(null)
const chartRef = shallowRef<ChartJS | null>(null)
expose({ chart: chartRef })
const renderChart = () => {
if (!canvasRef.value) return
const { type, data, options, plugins, datasetIdKey } = props
const clonedData = cloneData(data, datasetIdKey)
const proxiedData = cloneProxy(clonedData, data)
chartRef.value = new ChartJS(canvasRef.value, {
type,
data: proxiedData,
options: { ...options },
plugins
})
}
const destroyChart = () => {
const chart = toRaw(chartRef.value)
if (chart) {
chart.destroy()
chartRef.value = null
}
}
const update = (chart: ChartJS) => {
chart.update(props.updateMode)
}
onMounted(renderChart)
onBeforeUnmount(destroyChart)
watch(
[() => props.options, () => props.data],
(
[nextOptionsProxy, nextDataProxy],
[prevOptionsProxy, prevDataProxy]
) => {
const chart = toRaw(chartRef.value)
if (!chart) {
return
}
let shouldUpdate = false
if (nextOptionsProxy) {
const nextOptions = toRawIfProxy(nextOptionsProxy)
const prevOptions = toRawIfProxy(prevOptionsProxy)
if (nextOptions && nextOptions !== prevOptions) {
setOptions(chart, nextOptions)
shouldUpdate = true
}
}
if (nextDataProxy) {
const nextLabels = toRawIfProxy(nextDataProxy.labels)
const prevLabels = toRawIfProxy(prevDataProxy.labels)
const nextDatasets = toRawIfProxy(nextDataProxy.datasets)
const prevDatasets = toRawIfProxy(prevDataProxy.datasets)
if (nextLabels !== prevLabels) {
setLabels(chart.config.data, nextLabels)
shouldUpdate = true
}
if (nextDatasets && nextDatasets !== prevDatasets) {
setDatasets(chart.config.data, nextDatasets, props.datasetIdKey)
shouldUpdate = true
}
}
if (shouldUpdate) {
update(chart)
}
},
{ deep: true }
)
return () => {
return h('canvas', {
ref: canvasRef
})
}
}
}) as ChartComponent