首页 > 解决方案 > 如何在不与 svelte 中的编译器对抗的情况下避免循环依赖?

问题描述

我正在阅读该文档,在调整了它的示例代码之后,我设法让编译器向我咆哮了这样的循环依赖:

<script>
    let count = 0;
    $: double = count * 2;

    $: if (double >= 20) {
        alert(`count is dangerously high!`);
        count = 9;
    }

    function handleClick() {
        count += 1;
    }
</script>

<button on:click={handleClick}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

我在不和谐中询问如何修复它,人们建议我应该像这样隐藏编译器的依赖项:

<script>
    let count = 0;
    $: double = count * 2;

    function resetCount() {
        count = 9;
    }

    $: if (double >= 20) {
        alert(`count is dangerously high!`);
        resetCount();
    }

    function handleClick() {
        count += 1;
    }
</script>

<button on:click={handleClick}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

它有效,但我有几个问题:

  1. 与编译器战斗对我来说听起来不对,还有其他更好的方法来解决这个问题吗?
  2. 一个更普遍的问题是,循环依赖是否经常发生在编写大量苗条代码的人身上?这是正常的还是通常表明设计不好?

谢谢。

标签: javascriptreactive-programmingsvelte

解决方案


@morphyish 的答案提供了一个修复,因为正如他们所说:

反应式语句不能自行触发

但是,我认为这有点技术性,并且仍然认为提供的解决方案在概念上具有循环依赖:我们仍然有count -> double -> count -> ....

而且因为我们通过将语句合并到单个反应块中绕过了这个循环依赖警告,我们实际上还引入了一个错误:

在此处输入图像描述

发生此错误是因为在反应块的开头将double值设置为= 20,然后在 if 语句中设置为,但由于反应块不再触发,因此未设置回该值。10 * 2count9double9 * 2 = 18

我在此和类似情况下的建议是重新评估您的依赖项实际上是什么,以消除这些循环:

double = count * 2;

^ 所以double取决于count,这很容易。

if (double >= 20) {
  alert('count is dangerously high!');
  count = 9;
}

^ 乍一看,我们的计数重置逻辑似乎依赖于double,但鉴于我们已经确定double依赖于count,并且这个块最终关注的是count,这个逻辑实际上依赖于count而不是 double

因此,在我看来,最好的解决方案是修改条件以匹配实际依赖项:

<script>
    let count = 0;
    $: double = count * 2;

    $: if (count >= 10) {
        alert(`count is dangerously high!`);
        count = 9;
    }

    function handleClick() {
        count += 1;
    }
</script>

<button on:click={handleClick}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
</button>


推荐阅读