当需要访问和更新 DOM 元素时,如何在 Svelte/Sapper 中编写响应式语句?

How do you write a reactive statement in Svelte/Sapper when it needs to access and update a DOM element?

我正在尝试编写一个函数 drawChart,每次我的变量 stats 更改时都会调用该函数以更新我当前的图表。

我可以在使用 onMount 时绘制我的初始图表,但是当我获取新的统计数据时,图表不会更新。

我不知道如何在 Sapper 中执行此操作,因为我的函数还依赖于 canvas 元素用于我的图表上下文。

我尝试写一个响应式语句,例如 $: drawChart(chartContext, stats),但是 chartContext 是未定义的。

我的代码:

<script>
    import { onMount } from 'svelte';
    import Chart from 'chart.js';

    export let stats;

    let chartContext;
    let chartCanvas;
    let chart;

    onMount(() => {    
        chartContext = chartCanvas.getContext('2d');

        drawChart(chartContext, stats);
    })

    const drawChart = (chartContext, stats) => {
        const s = fetchStats(stats);

        chart = new Chart(chartContext, {
            type: 'bar',
            data: {
                labels: s.seasons,
                datasets: [{
                    label: s.stat1.label,
                    data: s.stat1.data,
                    backgroundColor: 'whitesmoke',
                    borderColor: 'black',
                    borderWidth: 1
                }]
            },
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                },
                maintainAspectRatio: false,
                responsive: true
            }
        });
    }

    // I want this to be called each time stats is updated, but it does not work as chartContext is undefined here
    $: drawChart(chartContext, stats);
</script>

<canvas id="chart" width="200" height="200" aria-label="chart" role="figure" bind:this={chartCanvas}></canvas>

有办法解决这个问题吗?非常感谢任何帮助:)

是的,当 chartContext 仍未定义时,预计您会得到反应块的 运行。它发生在 onMount 之前。 Svelte 只需 运行 任何因变量发生变化时的反应块,这包括它们的初始值。在运行宁反应块或类似的东西之前,Svelte 不会等待组件安装在 DOM 中。

所以您只需要在代码中考虑这种特殊情况:

$: if (chartContext) drawChart(chartContext, stats)

这里。搞定。 (您可能还想确保 stats 以相同的方式设置,以使您的组件对消费者可能发送给它的内容更具弹性。)