Как лучше всего реализовать модель данных с общим доступом в представлениях Svelte
У меня есть созданное мной представление, которое содержит форму, элементы управления этой формы привязаны к свойствам объекта модели, который также используется другими представлениями). Я пытаюсь понять, действительно ли использование парадигмы Store необходимо или рекомендуется.
Например, модель будет выглядеть примерно так:
model = {
foo: undefined,
bar: undefined,
baz: undefined
}
... и пользовательский интерфейс будет иметь различные входы, привязанные к модели, примерно так:
//example.svelte
<script>
import { exampleModel } from "./models.js";
</script>
<h2>Has foo?</h2>
<label for="input_foo_t">yes</label>
<input id="input_foo_t" type="radio" bind:group={exampleModel.foo} value={true}/>
<label for="input_foo_f">no</label>
<input id="input_foo_f" type="radio" bind:group={exampleModel.foo} value={false}/>
<h2>Has bar?</h2>
<label for="input_bar_t">yes</label>
<input id="input_bar_t" type="radio" bind:group={exampleModel.bar} value={true}/>
<label for="input_bar_f">no</label>
<input id="input_bar_f" type="radio" bind:group={exampleModel.bar} value={false}/>
В идеале хотелось бы сохранить тезисы как единое целое. Из всех примеров я вижу, что ничего подобного нет. Является ли намерение Svelte Stores предоставлять супер-детализированные данные для совместного использования, чтобы мы в основном "хранили" одно значение? Или есть примеры, которые показывают что-то вроде объекта модели, используемого в парадигме магазина? Мне не хватает какого-то процесса жизненного цикла, который мне нужно использовать с помощью Svelte Store (что-то вроде дайджеста Angular)?
2 ответа
Вы, безусловно, можете использовать для этого магазин:
// models.js
import { writable } from 'svelte/store';
export const exampleModel = writable({
foo: undefined,
bar: undefined,
baz: undefined,
});
//example.svelte
<script>
import { exampleModel } from "./models.js";
</script>
<h2>Has foo?</h2>
<label for="input_foo_t">yes</label>
<input id="input_foo_t" type="radio" bind:group={$exampleModel.foo} value={true}/>
<!-- etc -->
Сказав это, лучше не иметь огромных моделей, потому что изменение одного свойства приведет к проверке всех его зависимостей (т.е. если вы измените$exampleModel.foo
, ссылки на $exampleModel.bar
также будет обновляться, потому что для Svelte $exampleModel
это то, что изменилось). Обычно это не реальная проблема, но об этом нужно знать. Альтернатива, позволяющая избежать этого, - иметь более детальные значения:
// models.js
export const foo = writable();
export const bar = writable();
export const baz = writable();
Я создал два примера, которые демонстрируют, о чем говорит Рич.
Первый использует одну модель (с глубиной), содержащую все три переменные (демонстрация здесь: Svelte Store Granularity (Ver 1 Single Model)).
Установите флажок, чтобы изменить отдельную переменную. Подсчитанные изменения состояния (справа) показывают, что все три переменные ошибочно считаются измененными рефлексивно:-(
<script> const fooChangeCount = createReflectiveCounter(); const barChangeCount = createReflectiveCounter(); const bazChangeCount = createReflectiveCounter(); // monitor store-based state changes $: fooChangeCount.monitor($model.foo); $: barChangeCount.monitor($model.bar); $: bazChangeCount.monitor($model.baz); const reset = () => { fooChangeCount.reset(); barChangeCount.reset(); bazChangeCount.reset(); }; </script> <h2>Svelte Store Granularity</h2> <h4><i>(Ver 1 Single Model)</i></h4> <label><input type=checkbox bind:checked={$model.foo}> foo: (state changed {$fooChangeCount} times)</label> <label><input type=checkbox bind:checked={$model.bar}> bar: (state changed {$barChangeCount} times)</label> <label><input type=checkbox bind:checked={$model.baz}> baz: (state changed {$bazChangeCount} times)</label> <p><i>click to change each var: <b>state changes tallied to right</b></i></p> <button on:click={reset}>Reset Counts</button> <script context="module"> import {writable} from 'svelte/store'; const model = writable({ foo: undefined, bar: undefined, baz: undefined, }); function createReflectiveCounter() { // our base writable store // ... -1 accounts for our initial monitor reflection (bumping it to 0) const {subscribe, set, update} = writable(-1); // expose our newly created custom store return { subscribe, monitor() { update((count) => count + 1); // increment our count return ''; // see JavaDoc }, reset: () => set(0) }; } </script>
Второй использует несколько моделей, по одной для каждой из трех переменных (демонстрация здесь: Svelte Store Granularity (Ver 2 Multiple Models)).
В этом случае подсчитанные изменения состояния (справа) теперь правильно показывают, что только фактически измененная переменная считается рефлексивной:-)
<script> const fooChangeCount = createReflectiveCounter(); const barChangeCount = createReflectiveCounter(); const bazChangeCount = createReflectiveCounter(); // monitor store-based state changes $: fooChangeCount.monitor($foo); $: barChangeCount.monitor($bar); $: bazChangeCount.monitor($baz); const reset = () => { fooChangeCount.reset(); barChangeCount.reset(); bazChangeCount.reset(); }; </script> <h2>Svelte Store Granularity</h2> <h4><i>(Ver 2 Multiple Models)</i></h4> <label><input type=checkbox bind:checked={$foo}> foo: (state changed {$fooChangeCount} times)</label> <label><input type=checkbox bind:checked={$bar}> bar: (state changed {$barChangeCount} times)</label> <label><input type=checkbox bind:checked={$baz}> baz: (state changed {$bazChangeCount} times)</label> <!-- Diagnostic: monitor store-based state changes --> <p><i>click to change each var: <b>state changes tallied to right</b></i></p> <button on:click={reset}>Reset Counts</button> <script context="module"> import {writable} from 'svelte/store'; const foo = writable(); const bar = writable(); const baz = writable(); function createReflectiveCounter() { // our base writable store // ... -1 accounts for our initial monitor reflection (bumping it to 0) const {subscribe, set, update} = writable(-1); // expose our newly created custom store return { subscribe, monitor() { update((count) => count + 1); // increment our count return ''; // see JavaDoc }, reset: () => set(0) }; } </script>
Надеюсь это поможет!
</Kevin>