我拥有一个相当小巧的苗条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>
答案 0 :(得分:0)
将$: question = getQuestion(page);
替换为:
$: question = setup[Object.keys(setup)[page || 0]];
https://svelte.dev/repl/f7c2a4119829442a8e46ebb557bf1cf8?version=3.29.4
反应性声明的工作方式是精简分析并提取其依赖的参数。对于$: question = getQuestion(page);
,相关性为getQuestion
和page
,并且每当它们更改时,question
都会重新计算。
但是getQuestion
和page
从未改变,因此question
从未重新计算。
因此,您想要的是question
发生变化时重新计算setup
,并且需要确保question
依赖于setup
。
换句话说,您需要反应性声明以具有此表单
$: question = ...setup...
这一原则也在这一行中发生
class={isSelected(option) ? 'selected' : ''}
Svelte对其进行解析,并将其提取为依赖项isSelected
和option
,并在它们中的任何一个改变时重新计算“类属性”。
但是现在您可能会想起来... 嘿!但它们永远不会改变,所以这怎么工作?。
原因是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在反应性声明
中的作用。