Vue 3 + ChartJS 4. The headline change is that the component now tracks its props — the update() calls v2 required are no longer needed.
⚠️ Breaking
preventDefault() applies to one emission. In v2 a single call canceled that hook for the lifetime of the chart, because the event object was created once and its flag never reset — so a conditional guard froze the chart permanently the first time its condition was true.
// v2: ran once, then the hook was canceled forever
const onBeforeDraw = (event) => {
if (isFirstRender) { event.preventDefault(); isFirstRender = false }
}
// v3: to suppress a hook permanently, cancel unconditionally
const onBeforeDraw = (event) => event.preventDefault()Features
Every prop is reactive. data and options changes update the chart; type, height and width rebuild it. Both are debounced, so a burst of changes costs one update.
// v2
chart.data.datasets[0].data = [1, 2, 3]
chartRef.value.update()
// v3
chart.data.datasets[0].data = [1, 2, 3]autoUpdate: false opts out. The watchers are removed rather than disabled, so the deep walk over data stops costing anything — ten mutations of a fifty-thousand-point dataset go from ~476ms to none. Existing update() calls keep working either way, so this also restores v2 behaviour verbatim.
EventObject and UpdateMode are exported, so event handlers and update calls can be typed.
Fixes
- Types resolve on modern module resolution. The
exportsmap now declares atypescondition, and ChartJS types come from its public entry rather thanchart.js/dist/types. Consumers onbundler,node16ornodenextpreviously got no types at all, or silently degraded toanyunderskipLibCheck. update()no longer copies ChartJS's resolved options proxy, which threwname.startsWith is not a functionwhenever theoptionsprop was replaced rather than mutated.- Replacing a whole prop object works. v2 held a snapshot taken at setup, so only in-place mutation had any effect.
- The chart is destroyed on unmount, so
destroy()no longer has to be called by hand. - Plugin state survives a data change. Only the changed prop is reassigned, so a chart zoomed with
chartjs-plugin-zoomholds its range while its data updates.
Also
update() takes a ChartJS transition mode, not an animation duration — changed in 2.1.0 but undocumented until now. update(750) is silently ignored; set options.animation.duration instead.
Full notes, including the two caveats worth reading before relying on the reactivity, are in Migrating from v2.