У меня есть родительский шаблон (App.svelte), который создает массив доступных для записи и передает его компоненту (RedOrBlueOrPurple.svelte
). Компонент перебирает элементы. Я хочу передать массив объектов для записи (а не создавать одну доступную для записи, содержащую весь массив объектов), потому что я хочу добавить subscribe
обработчиков для каждого элемента индивидуально, когда что-то меняется внутри элемента. В противном случае обработчик подписки должен был бы выяснить, какой элемент был изменен, что, похоже, требует больше работы.
В приведенном ниже коде первая кнопка действительно изменяет фиолетовый атрибут, потому что за вызовом update
следует refresh
, который сбрасывает родительские значения. Я бы хотел избежать этого вызова, если это возможно, и просто использовать доступный для записи интерфейс, который понимают и могут использовать как родитель, так и ребенок.
Кроме того, мне не нравится, что шаблон должен использовать map
на каждом, чтобы вытащить элемент, получить значение магазина (с помощью внутреннего вызова svelte get_store_value
), но я не знаю, как бы я использовал {#each items as $items...}
в противном случае (Я не могу понять, как использовать здесь $item
). Есть ли более элегантный способ получить ценность?
Кроме того, и это кажется действительно прискорбным, тот факт, что консоль не отображает ошибки, когда я вызываю обновление и устанавливаю переменную const
, кажется, что он нарушает правила JS и все еще компилируется. Я знаю, что Svelte аннотирует этот вызов под капотом, чтобы отреагировать на изменение, но это кажется неправильным.
Это здесь REPL: https://svelte.dev/repl/84fbae4358494844a79a7f119b084f01?version=3.19.2
<script>
import { writable } from 'svelte/store';
import RedOrBlueOrPurple from './RedOrBlueOrPurple.svelte';
const items = [];
items.push( writable( { blue: true }));
items.push( writable( { blue: false, red: true }));
items.push( writable( { blue: true, red: true }));
const refresh = () => {
items = items;
};
</script>
<RedOrBlueOrPurple {refresh} {items}/>
<script>
import { get_store_value } from 'svelte/internal';
export let items;
export let refresh;
const purple = (item, callRefresh) => {
item.update( i => {
i.purple = true;
return i;
});
// We only call this for the first button, and if we don't,
// the items aren't updated, even though we do call update on
// the store correctly.
if (callRefresh) {
refresh();
}
};
</script>
{#each items.map( item => ({ item, value: get_store_value(item) })) as { item, value}, index }
<h1>
Item : { index }
</h1>
<div>
RED: { value.red ? "Red" : "Not red"}
</div>
<div>
BLUE: { value.blue ? "Blue" : "Not blue"}
</div>
<div>
PURPLE: { value.purple ? "Purple" : "Not purple"}
</div>
<button on:click={ () => { purple(item, index === 0) } }>Change to purple</button>
{/each}