如何在 Svelte 视图中最好地实现可共享数据模型
How to best implement a shareable data model in Svelte views
我创建了一个包含表单的视图,该表单的控件绑定到 Model 对象的属性,该对象也由其他视图共享)。我想弄清楚是否真的有必要或推荐使用 Store 范例。
例如模型看起来有点像:
model = {
foo: undefined,
bar: undefined,
baz: undefined
}
... 而 UI 将通过如下方式将各种输入绑定到模型:
//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 的目的是提供超细化、可共享的数据,以便我们基本上 "storing" 一个单一的价值吗?或者是否有示例显示在商店范例中使用的模型对象之类的东西?我是否错过了一些我需要通过使用 Svelte Store(类似于 Angular 的摘要)来利用的生命周期过程?
您当然可以为此使用商店:
// 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();
我创建了两个示例来演示 Rich 所说的内容。
第一个使用单个模型(具有深度)保存所有三个变量(此处演示: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>
我创建了一个包含表单的视图,该表单的控件绑定到 Model 对象的属性,该对象也由其他视图共享)。我想弄清楚是否真的有必要或推荐使用 Store 范例。
例如模型看起来有点像:
model = {
foo: undefined,
bar: undefined,
baz: undefined
}
... 而 UI 将通过如下方式将各种输入绑定到模型:
//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 的目的是提供超细化、可共享的数据,以便我们基本上 "storing" 一个单一的价值吗?或者是否有示例显示在商店范例中使用的模型对象之类的东西?我是否错过了一些我需要通过使用 Svelte Store(类似于 Angular 的摘要)来利用的生命周期过程?
您当然可以为此使用商店:
// 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();
我创建了两个示例来演示 Rich 所说的内容。
第一个使用单个模型(具有深度)保存所有三个变量(此处演示: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>