更改对象时dom不更新

时间:2020-11-01 17:46:57

标签: svelte

我拥有一个相当小巧的苗条Webapp,目前仅是一个问卷。我正在尝试创建一种多选系统,您可以在其中单击一堆按钮并将其标记为选中状态(几乎是一个html复选框,但是略微离题)。

因此,为了向用户显示已选择了一个选项,如果要选择一个类,我想向按钮添加一个类。但是它没有被更新,我真的不知道为什么。 isSelected函数在每个选项中仅被调用一次,而在修改安装对象时则永远不会调用,我想知道为什么会这样

    <script>
      let page = 0;
      let setup = {
        JLPT: {
          question: "select JLPT levels",
          options: [1, 2, 3, 4, 5, 6, 7, 8, 9],
          selected: [],
          onSelect: option => {
            console.log(setup.JLPT.selected);
            setup.JLPT.selected = setup.JLPT.selected.concat(option);
          }
        }
      };
      $: question = getQuestion(page);
    
      function getQuestion(page) {
        return setup[Object.keys(setup)[page || 0]];
      }
    
      function isSelected(option) {
        return (question.selected || []).indexOf(option) > -1;
      }
    
      function onClick(option) {
        getQuestion(page).onSelect(option);
      }
    </script>
    
    
    <div class="wrapper">
      <div class="question">{question.question}</div>
      <div class="input">
        {#each question.options as option}
          <button
            on:click={() => onClick(option)}
            class={isSelected(option) ? 'selected' : ''}>
            {option}
          </button>
        {/each}
      </div>
    </div>

1 个答案:

答案 0 :(得分:0)

$: question = getQuestion(page);替换为:

$: question = setup[Object.keys(setup)[page || 0]];

https://svelte.dev/repl/f7c2a4119829442a8e46ebb557bf1cf8?version=3.29.4

为什么?

反应性声明的工作方式是精简分析并提取其依赖的参数。对于$: question = getQuestion(page);,相关性为getQuestionpage,并且每当它们更改时,question都会重新计算。

但是getQuestionpage从未改变,因此question从未重新计算。

因此,您想要的是question发生变化时重新计算setup,并且需要确保question依赖于setup

换句话说,您需要反应性声明以具有此表单

$: question = ...setup...

这一原则也在这一行中发生

class={isSelected(option) ? 'selected' : ''}

Svelte对其进行解析,并将其提取为依赖项isSelectedoption,并在它们中的任何一个改变时重新计算“类属性”。

但是现在您可能会想起来... 嘿!但它们永远不会改变,所以这怎么工作?

原因是option属于#each block的一部分,而question取决于setup
因此,每当setup发生变化(标记为“脏”)时,question都会重新计算并标记为“脏”,因此每个“类属性”都会重新计算,因为它们都间接依赖于question


顺便说一句:一种更好的动态分配类的解决方案是使用the class directive

class:selected={isSelected(option)}

您可能想阅读这篇https://lihautan.com/compile-svelte-in-your-head-part-2/#reactive-declaration帖子,以便更好地了解Svelte在反应性声明

中的作用。