Да и нет.
Фактически, то, что вы сделали, связывает переменную между различными экземплярами компонента. Объект тот же ===
с той же ссылкой ... Пока это не произойдет:
selection = value;
Это из скомпилированного кода вашего REPL. Когда вы устанавливаете флажок, Svelte создает новый массив, содержащий отмеченные значения, и присваивает его переменной bind:group
. На данный момент переменная все та же ... Но ее содержимое было заменено новой ссылкой на массив. Поэтому при смене группы вы теряете ценность предыдущей.
Вы можете доказать это себе, обновив свой REPL, сделав selection
объектом вместо массива, и добавив некоторую логику для хранения значения по ключу.
Например, в App.svelte измените выделение на объект:
let selection = {};
А в Selector.svelte привяжите к промежуточной переменной и напишите только свойства объекта (а не сам объект):
<script>
export let options;
export let selection;
let group = []
$: for (const option of options) {
selection[option] = group.includes(option)
}
</script>
<div class="selector">
{#each options as option}
<label>
<input type="checkbox" value={option} bind:group />
{option}
</label>
{/each}
</div>
Обновленный REPL
Каким-то образом распечатайте значение selection
, и вы увидите, что оно не сбрасывается и содержит значение из всех селекторов.
Итак, возвращаясь к вашей проблеме, проблема на самом деле заключается в назначении. И напрямую с этим ничего не поделаешь. В Svelte нет ничего для объединения связанных значений ... Однако теперь, когда мы поняли проблему, мы можем ее обойти.
Решение состоит в том, чтобы не связывать напрямую общедоступную опору (т.е. selection
), а вместо этого привязываться к промежуточной переменной, как в нашем предыдущем примере, и каким-то образом самостоятельно выполнять слияние (здесь доступно множество способов).
Вот один из способов переписать компонент Selector, чтобы разрешить совместное использование переменных:
<script>
export let options;
export let selection;
let group = []
const update = () => {
selection = selection
.filter(x => !options.includes(x))
.concat(group)
}
// when group changes, update
$: group, update()
</script>
<div class="selector">
{#each options as option}
<label>
<input type="checkbox" value={option} bind:group />
{option}
</label>
{/each}
</div>
REPL
Примечание: я не помещал выражение selection = selection.filter(x => !options.includes(x)).concat(group)
непосредственно в реактивный блок, потому что наше обновление будет запускаться при изменении selection
. А поскольку он общий, он изменится снаружи. Фактически, это было бы условием бесконечного цикла, но у Svelte есть защита специально от этого (для реактивных блоков). Но лучше не полагаться на это, а также не тратить зря. Здесь он сработает только при изменении нашего локального group
, а это как раз то, что нам нужно.
01.04.2020
selection
. 01.04.2020