英文:
Cannot read properties of undefined (reading 'notifyPlugins') - chart.js
问题
我明白你的要求,以下是翻译好的部分:
问题描述:
当从图表页面导航离开时,为什么我的图表会尝试读取 notifyPlugins('beforeDestroy')
?
我有一个插件文件、一个 Svelte 动作以及一个主文件 [ChartMetrics.svelte](其中使用了该动作)。当前的行为是,在主页面中图表完全正常加载,但当导航到另一个页面时,我遇到了 notifyPlugins
错误。我已经添加了项目中最相关的代码,因为整个代码库相当大,无法将其添加到 CodeSandbox。是否有人在使用 chart.js 时曾遇到过 notifyPlugins
错误?如果你需要看更多代码,请告诉我。
控制台错误:
chart.js:6171 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'notifyPlugins')
at destroy (chart.js:6171:1)
at Object.destroy [as d] (ChartMetrics.svelte:454:1)
at Object.destroy [as d] (Div.svelte:127:1)
at destroy_component (index.mjs:1974:1)
at Object.destroy [as d] (ChartMetrics.svelte:127:1)
at Object.destroy [as d] (ChartMetrics.svelte:535:1)
at destroy_component (index.mjs:1974:1)
at Object.destroy [as d] (EffectiveMaterialAssetsMetricsContainer.svelte:71:1)
at Object.destroy [as d] (MetricWrapper.svelte:133:1)
at Object.destroy [as d] (MetricWrapper.svelte:308:1)
chart.js (第6171行):
destroy() {
this.notifyPlugins('beforeDestroy');
....
}
ChartMetrics (第454行):
d: function destroy(detaching) {
if (detaching) detach_dev(div0);
if_blocks[current_block_type_index].d();
destroy_component(tooltipinfo);
destroy_component(anchor);
if (detaching) detach_dev(t3);
if (detaching) detach_dev(div1);
mounted = false;
dispose();
}
ChartMetrics 第454行(图像):
plugins.ts:
export function textPlugin(value: number, theme: Theme) {
return {
id: "chartTextPlugin",
// 在图表中间写入文本的插件
beforeDraw: function (chart: ChartType) {
// 在 chart.js 图表上绘制一些文本的插件
},
}
}
export function curvePlugin() {
// 曲线化环形图的边缘
return {
id: "chartCurvePlugin",
afterUpdate: function (chart: ChartType) {
// 一些代码来曲线化 chart.js 图表的边缘
},
afterDraw: function (chart: ChartType) {
// 一些代码来执行与上面相同的操作
},
}
}
add-chart.ts(Svelte 动作):
export const addChart = (node: HTMLElement, params: ChartProps): ChartGauge => {
const text = textPlugin(params.value, params.theme);
const curve = curvePlugin();
const backgroundColor = mapTypeToColor(params.theme);
return new Chart(node, {
type: "doughnut",
data: {
datasets: [
{
//label: params.caption,
data: [params.value, 100 - params.value],
backgroundColor: backgroundColor,
borderColor: ["rgba(255, 255, 255 ,1)"],
borderWidth: 0,
},
],
},
options: {
rotation: -90,
cutout: "85%",
circumference: 180,
radius: "85%",
responsive: true,
maintainAspectRatio: true,
aspectRatio: 3,
},
plugins: [text, curve],
});
}
ChartMetrics.svelte:
{#if value >= 0 && value <= 100}
<CardDiv p={4} pl={4} pr={4}>
<div class="metrics-header">
<h3>
Controls -
{#if titleUrl}
<Anchor href={titleUrl} size={14}>{title}</Anchor>
{:else}
<span>{title}</span>
{/if}
<TooltipInfo content={tooltipContent} id="info" width="small" />
</h3>
<Anchor href={assuranceUrl} size={14}>View Assurance</Anchor>
</div>
<div class="chart">
<canvas
id="chart"
data-test-id="chart"
use:addChart={{ value, theme }}
style="height:100%;width:100%;"
/>
</div>
</CardDiv>
{:else}
<MetricsError message="Chart Metrics Widget Error: Invalid value." />
{/if}
希望这些翻译对你有所帮助。如果有其他问题,请随时提出。
英文:
Why is my chart attempting to read notifyPlugins('beforeDestroy') when navigating away from the page of the chart?
I have a plugins file, a svelte action and a main file [ChartMetrics.svelte] (where the action is used). The current behaviour is that the chart loads completely fine in the main page, but when navigating to another page I am met with the notifyPlugins error. I have added the most relevant code from my project, as the entire codebase is quite large so would be unable to add it to a codesandbox. Has anyone recieved this error with notifyPlugins before when working with chart.js? If there is any more code you need to see let me know.
console error:
chart.js:6171 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'notifyPlugins')
at destroy (chart.js:6171:1)
at Object.destroy [as d] (ChartMetrics.svelte:454:1)
at Object.destroy [as d] (Div.svelte:127:1)
at destroy_component (index.mjs:1974:1)
at Object.destroy [as d] (ChartMetrics.svelte:127:1)
at Object.destroy [as d] (ChartMetrics.svelte:535:1)
at destroy_component (index.mjs:1974:1)
at Object.destroy [as d] (EffectiveMaterialAssetsMetricsContainer.svelte:71:1)
at Object.destroy [as d] (MetricWrapper.svelte:133:1)
at Object.destroy [as d] (MetricWrapper.svelte:308:1)
chart.js (line 6171):
destroy() {
this.notifyPlugins('beforeDestroy');
....
}
ChartMetrics (line 454):
d: function destroy(detaching) {
if (detaching) detach_dev(div0);
if_blocks[current_block_type_index].d();
destroy_component(tooltipinfo);
destroy_component(anchor);
if (detaching) detach_dev(t3);
if (detaching) detach_dev(div1);
mounted = false;
dispose();
}
ChartMetrics line 454 (image):
plugins.ts:
export function textPlugin(value: number, theme: Theme) {
return {
id: "chartTextPlugin",
// Plugin for writing text in middle of chart
beforeDraw: function (chart: ChartType) {
plugin that draws some text on a chart.js chart
},
}
}
export function curvePlugin() {
// Curve edges of donut
return {
id: "chartCurvePlugin",
afterUpdate: function (chart: ChartType) {
// some code to curve the edges of the chart.js chart
}
},
afterDraw: function (chart: ChartType) {
// some more code to do same as above
},
}
}
add-chart.ts (svelte action)
export const addChart = (node: HTMLElement, params: ChartProps): ChartGauge => {
const text = textPlugin(params.value, params.theme)
const curve = curvePlugin()
const backgroundColor = mapTypeToColor(params.theme)
return new Chart(node, {
type: "doughnut",
data: {
datasets: [
{
//label: params.caption,
data: [params.value, 100 - params.value],
backgroundColor: backgroundColor,
borderColor: ["rgba(255, 255, 255 ,1)"],
borderWidth: 0,
},
],
},
options: {
rotation: -90,
cutout: "85%",
circumference: 180,
radius: "85%",
responsive: true,
maintainAspectRatio: true,
aspectRatio: 3,
},
plugins: [text, curve],
})
}
ChartMetrics.svelte
{#if value >= 0 && value <= 100}
<CardDiv p={4} pl={4} pr={4}>
<div class="metrics-header">
<h3>
Controls -
{#if titleUrl}
<Anchor href={titleUrl} size={14}>{title}</Anchor>
{:else}
<span>{title}</span>
{/if}
<TooltipInfo content={tooltipContent} id="info" width="small" />
</h3>
<Anchor href={assuranceUrl} size={14}>View Assurance</Anchor>
</div>
<div class="chart">
<canvas
id="chart"
data-test-id="chart"
use:addChart={{ value, theme }}
style="height:100%;width:100%;"
/>
</div>
</CardDiv>
{:else}
<MetricsError message="Chart Metrics Widget Error: Invalid value." />
{/if}
答案1
得分: 0
你可以尝试这个解决方案的补丁:在 add-chart.ts
中,替换
return new Chart(node, {
.....
});
使用
const chart = new Chart(node, {
......
});
chart.destroy = chart.destroy.bind(chart);
return chart;
更符合 Svelte 风格的方式可能是
return {
...chart,
destroy(){
chart.destroy();
}
}
但这可能需要一些 TypeScript 的技巧来通过类型检查。
英文:
You could try this patch of a solution: in add-chart.ts
instead of
return new Chart(node, {
.....
});
use
const chart = new Chart(node, {
.....
});
chart.destroy = chart.destroy.bind(chart);
return chart;
A more svelte-idiomatic way might be
return {
...chart,
destroy(){
chart.destroy();
}
}
but that would probably need some typescript acrobatics to pass type-checking.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论