跳至主要内容

运行时

svelte/store

在 GitHub 上编辑此页面

svelte/store 模块导出用于创建 可读可写派生 存储区的函数。

请记住,您不必使用这些函数在组件中享受 响应式 $store 语法。任何正确实现 .subscribe、取消订阅和(可选).set 的对象都是一个有效的存储区,并且既适用于特殊语法,也适用于 Svelte 的内置 derived 存储区

这使得几乎任何其他响应式状态处理库都可以包装起来,以便在 Svelte 中使用。阅读更多有关 存储区契约 的信息,以了解正确的实现是什么样的。

writable

ts
function writable<T>(
value?: T | undefined,
start?: StartStopNotifier<T> | undefined
): Writable<T>;

用于创建存储的功能,该存储的值可以从“外部”组件设置。它作为具有附加setupdate方法的对象创建。

set是一个方法,它接受一个参数,该参数是要设置的值。如果存储值尚未等于该值,则存储值将被设置为该参数的值。

update是一个方法,它接受一个参数,该参数是一个回调。回调将现有存储值作为其参数,并返回要设置为存储的新值。

store.js
ts
import { writable } from 'svelte/store';
const count = writable(0);
count.subscribe((value) => {
console.log(value);
}); // logs '0'
count.set(1); // logs '1'
count.update((n) => n + 1); // logs '2'
store.ts
ts
import { writable } from 'svelte/store';
const count = writable(0);
count.subscribe((value) => {
console.log(value);
}); // logs '0'
count.set(1); // logs '1'
count.update((n) => n + 1); // logs '2'

如果将函数作为第二个参数传递,则当订阅者数量从零变为一(但不是从一变为二等)时,将调用该函数。该函数将被传递一个set函数,该函数更改存储的值,以及一个update函数,该函数的工作方式类似于存储上的update方法,它采用一个回调函数从其旧值计算存储的新值。它必须返回一个stop函数,该函数在订阅者数量从一变为零时调用。

store.js
ts
import { writable } from 'svelte/store';
const count = writable(0, () => {
console.log('got a subscriber');
return () => console.log('no more subscribers');
});
count.set(1); // does nothing
const unsubscribe = count.subscribe((value) => {
console.log(value);
}); // logs 'got a subscriber', then '1'
unsubscribe(); // logs 'no more subscribers'
store.ts
ts
import { writable } from 'svelte/store';
const count = writable(0, () => {
console.log('got a subscriber');
return () => console.log('no more subscribers');
});
count.set(1); // does nothing
const unsubscribe = count.subscribe((value) => {
console.log(value);
}); // logs 'got a subscriber', then '1'
unsubscribe(); // logs 'no more subscribers'

请注意,当writable被销毁(例如在刷新页面时)时,其值将丢失。但是,您可以编写自己的逻辑,例如将值同步到localStorage

readable

ts
function readable<T>(
value?: T | undefined,
start?: StartStopNotifier<T> | undefined
): Readable<T>;

创建无法从“外部”设置其值的存储,第一个参数是存储的初始值,第二个参数readablewritable的第二个参数相同。

ts
import { readable } from 'svelte/store';
const time = readable(new Date(), (set) => {
set(new Date());
const interval = setInterval(() => {
set(new Date());
}, 1000);
return () => clearInterval(interval);
});
const ticktock = readable('tick', (set, update) => {
const interval = setInterval(() => {
update((sound) => (sound === 'tick' ? 'tock' : 'tick'));
}, 1000);
return () => clearInterval(interval);
});

derived

ts
function derived<S extends Stores, T>(
stores: S,
fn: (
values: StoresValues<S>,
set: (value: T) => void,
update: (fn: Updater<T>) => void
) => Unsubscriber | void,
initial_value?: T | undefined
): Readable<T>;
ts
function derived<S extends Stores, T>(
stores: S,
fn: (values: StoresValues<S>) => T,
initial_value?: T | undefined
): Readable<T>;

从一个或多个其他存储中派生存储。当第一个订阅者订阅时,回调最初运行,然后在存储依赖项发生更改时运行。

在最简单的版本中,derived采用单个存储,并且回调返回派生值。

ts
import { derived } from 'svelte/store';
const doubled = derived(a, ($a) => $a * 2);

回调可以通过接受第二个参数set和可选的第三个参数update来异步设置值,在适当的时候调用它们中的一个或两个。

在这种情况下,你还可以将第三个参数传递给 derived — 派生存储的初始值,在首次调用 setupdate 之前。如果没有指定初始值,则存储的初始值将为 undefined

ts
import { derived } from 'svelte/store';
const delayed = derived(
a,
($a, set) => {
setTimeout(() => set($a), 1000);
},
2000
);
const delayedIncrement = derived(a, ($a, set, update) => {
set($a);
setTimeout(() => update((x) => x + 1), 1000);
// every time $a produces a value, this produces two
// values, $a immediately and then $a + 1 a second later
});

如果你从回调函数返回一个函数,则会在以下情况下调用该函数:a) 回调函数再次运行,或 b) 最后一个订阅者取消订阅。

ts
import { derived } from 'svelte/store';
const tick = derived(
frequency,
($frequency, set) => {
const interval = setInterval(() => {
set(Date.now());
}, 1000 / $frequency);
return () => {
clearInterval(interval);
};
},
2000
);

在这两种情况下,都可以将参数数组作为第一个参数传递,而不是单个存储。

ts
import { derived } from 'svelte/store';
const summed = derived([a, b], ([$a, $b]) => $a + $b);
const delayed = derived([a, b], ([$a, $b], set) => {
setTimeout(() => set($a + $b), 1000);
});

readonly

ts
function readonly<T>(store: Readable<T>): Readable<T>;

这个简单的帮助器函数使存储变为只读。你仍然可以使用这个新的可读存储订阅原始存储的更改。

ts
import { readonly, writable } from 'svelte/store';
const writableStore = writable(1);
const readableStore = readonly(writableStore);
Property 'set' does not exist on type 'Readable<number>'.2339Property 'set' does not exist on type 'Readable<number>'.
readableStore.subscribe(console.log);
writableStore.set(2); // console: 2
readableStore.set(2); // ERROR

get

ts
function get<T>(store: Readable<T>): T;

通常,你应该通过订阅存储并随着时间的推移使用值来读取存储的值。有时,你可能需要检索未订阅的存储的值。get 允许你这样做。

它的工作原理是创建订阅,读取值,然后取消订阅。因此,不建议在热代码路径中使用它。

ts
import { get } from 'svelte/store';
const value = get(store);

类型

Readable

用于订阅的可读接口。

ts
interface Readable<T> {}
ts
subscribe(this: void, run: Subscriber<T>, invalidate?: Invalidator<T>): Unsubscriber;
  • run 订阅回调
  • invalidate 清理回调

订阅值更改。

StartStopNotifier

启动和停止通知回调。当第一个订阅者订阅时调用此函数。

ts
type StartStopNotifier<T> = (
set: (value: T) => void,
update: (fn: Updater<T>) => void
) => void | (() => void);

Subscriber

通知值更新的回调。

ts
type Subscriber<T> = (value: T) => void;

Unsubscriber

取消订阅值更新。

ts
type Unsubscriber = () => void;

Updater

更新值的回调。

ts
type Updater<T> = (value: T) => T;

Writable

用于更新和订阅的可写接口。

ts
interface Writable<T> extends Readable<T> {}
ts
set(this: void, value: T): void;
  • 要设置的 value

设置值并通知订阅者。

ts
update(this: void, updater: Updater<T>): void;
  • updater 回调

使用回调更新值并通知订阅者。

上一个 svelte
下一步 svelte/motion