Skip to main content

svelte/reactivity

Svelte 提供了各种内置函数的响应式版本,如MapSetURL,它们可以像它们的原生版本一样使用,同时还提供了一些额外的处理响应式的实用工具。

import {
	class MediaQuery

Creates a media query and provides a current property that reflects whether or not it matches.

Use it carefully — during server-side rendering, there is no way to know what the correct value should be, potentially causing content to change upon hydration. If you can use the media query in CSS to achieve the same effect, do that.

<script>
	import { MediaQuery } from 'svelte/reactivity';

	const large = new MediaQuery('min-width: 800px');
</script>

<h1>{large.current ? 'large screen' : 'small screen'}</h1>
@extendsReactiveValue<boolean> *
@since5.7.0
MediaQuery
,
class SvelteDate

A reactive version of the built-in Date object. Reading the date (whether with methods like date.getTime() or date.toString(), or via things like Intl.DateTimeFormat) in an effect or derived will cause it to be re-evaluated when the value of the date changes.

&#x3C;script>
	import { SvelteDate } from 'svelte/reactivity';

	const date = new SvelteDate();

	const formatter = new Intl.DateTimeFormat(undefined, {
	  hour: 'numeric',
	  minute: 'numeric',
	  second: 'numeric'
	});

	$effect(() => {
		const interval = setInterval(() => {
			date.setTime(Date.now());
		}, 1000);

		return () => {
			clearInterval(interval);
		};
	});
&#x3C;/script>

&#x3C;p>The time is {formatter.format(date)}&#x3C;/p>
SvelteDate
,
class SvelteMap<K, V>

A reactive version of the built-in Map object. Reading contents of the map (by iterating, or by reading map.size or calling map.get(...) or map.has(...) as in the tic-tac-toe example below) in an effect or derived will cause it to be re-evaluated as necessary when the map is updated.

Note that values in a reactive map are not made deeply reactive.

&#x3C;script>
	import { SvelteMap } from 'svelte/reactivity';
	import { result } from './game.js';

	let board = new SvelteMap();
	let player = $state('x');
	let winner = $derived(result(board));

	function reset() {
		player = 'x';
		board.clear();
	}
&#x3C;/script>

&#x3C;div class="board">
	{#each Array(9), i}
		&#x3C;button
			disabled={board.has(i) || winner}
			onclick={() => {
				board.set(i, player);
				player = player === 'x' ? 'o' : 'x';
			}}
		>{board.get(i)}&#x3C;/button>
	{/each}
&#x3C;/div>

{#if winner}
	&#x3C;p>{winner} wins!&#x3C;/p>
	&#x3C;button onclick={reset}>reset&#x3C;/button>
{:else}
	&#x3C;p>{player} is next&#x3C;/p>
{/if}
SvelteMap
,
class SvelteSet<T>

A reactive version of the built-in Set object. Reading contents of the set (by iterating, or by reading set.size or calling set.has(...) as in the example below) in an effect or derived will cause it to be re-evaluated as necessary when the set is updated.

Note that values in a reactive set are not made deeply reactive.

&#x3C;script>
	import { SvelteSet } from 'svelte/reactivity';
	let monkeys = new SvelteSet();

	function toggle(monkey) {
		if (monkeys.has(monkey)) {
			monkeys.delete(monkey);
		} else {
			monkeys.add(monkey);
		}
	}
&#x3C;/script>

{#each ['🙈', '🙉', '🙊'] as monkey}
	&#x3C;button onclick={() => toggle(monkey)}>{monkey}&#x3C;/button>
{/each}

&#x3C;button onclick={() => monkeys.clear()}>clear&#x3C;/button>

{#if monkeys.has('🙈')}&#x3C;p>see no evil&#x3C;/p>{/if}
{#if monkeys.has('🙉')}&#x3C;p>hear no evil&#x3C;/p>{/if}
{#if monkeys.has('🙊')}&#x3C;p>speak no evil&#x3C;/p>{/if}
SvelteSet
,
class SvelteURL

A reactive version of the built-in URL object. Reading properties of the URL (such as url.href or url.pathname) in an effect or derived will cause it to be re-evaluated as necessary when the URL changes.

The searchParams property is an instance of SvelteURLSearchParams.

Example:

&#x3C;script>
	import { SvelteURL } from 'svelte/reactivity';

	const url = new SvelteURL('https://example.com/path');
&#x3C;/script>

&#x3C;!-- changes to these... -->
&#x3C;input bind:value={url.protocol} />
&#x3C;input bind:value={url.hostname} />
&#x3C;input bind:value={url.pathname} />

&#x3C;hr />

&#x3C;!-- will update `href` and vice versa -->
&#x3C;input bind:value={url.href} size="65" />
SvelteURL
,
class SvelteURLSearchParams

A reactive version of the built-in URLSearchParams object. Reading its contents (by iterating, or by calling params.get(...) or params.getAll(...) as in the example below) in an effect or derived will cause it to be re-evaluated as necessary when the params are updated.

&#x3C;script>
	import { SvelteURLSearchParams } from 'svelte/reactivity';

	const params = new SvelteURLSearchParams('message=hello');

	let key = $state('key');
	let value = $state('value');
&#x3C;/script>

&#x3C;input bind:value={key} />
&#x3C;input bind:value={value} />
&#x3C;button onclick={() => params.append(key, value)}>append&#x3C;/button>

&#x3C;p>?{params.toString()}&#x3C;/p>

{#each params as [key, value]}
	&#x3C;p>{key}: {value}&#x3C;/p>
{/each}
SvelteURLSearchParams
,
function createSubscriber(start: (update: () => void) => (() => void) | void): () => void

Returns a subscribe function that, if called in an effect (including expressions in the template), calls its start callback with an update function. Whenever update is called, the effect re-runs.

If start returns a function, it will be called when the effect is destroyed.

If subscribe is called in multiple effects, start will only be called once as long as the effects are active, and the returned teardown function will only be called when all effects are destroyed.

It’s best understood with an example. Here’s an implementation of MediaQuery:

import { createSubscriber } from 'svelte/reactivity';
import { on } from 'svelte/events';

export class MediaQuery {
	#query;
	#subscribe;

	constructor(query) {
		this.#query = window.matchMedia(`(${query})`);

		this.#subscribe = createSubscriber((update) => {
			// when the `change` event occurs, re-run any effects that read `this.current`
			const off = on(this.#query, 'change', update);

			// stop listening when all the effects are destroyed
			return () => off();
		});
	}

	get current() {
		this.#subscribe();

		// Return the current state of the query, whether or not we're in an effect
		return this.#query.matches;
	}
}
@since5.7.0
createSubscriber
} from 'svelte/reactivity';

媒体查询

自 5.7.0 版本起可用

创建一个媒体查询并提供一个 当前 属性,该属性反映是否匹配。

请谨慎使用它——在服务器端渲染期间,无法知道正确的值应该是什么,这可能会导致内容在激活时发生变化。如果您可以使用 CSS 中的媒体查询达到相同的效果,请这样做。

<script>
	import { MediaQuery } from 'svelte/reactivity';

	const large = new MediaQuery('min-width: 800px');
</script>

<h1>{large.current ? 'large screen' : 'small screen'}</h1>
class MediaQuery extends ReactiveValue<boolean> {}
constructor(query: string, fallback?: boolean | undefined);
  • 查询 媒体查询字符串
  • 后备 服务器后备值

SvelteDate

一个内置的 日期 对象的响应式版本。读取日期(无论是使用 date.getTime()date.toString() 等方法,还是通过 Intl.DateTimeFormat 等方式),在 效果派生 中将导致在日期值变化时重新评估。

<script>
	import { SvelteDate } from 'svelte/reactivity';

	const date = new SvelteDate();

	const formatter = new Intl.DateTimeFormat(undefined, {
	  hour: 'numeric',
	  minute: 'numeric',
	  second: 'numeric'
	});

	$effect(() => {
		const interval = setInterval(() => {
			date.setTime(Date.now());
		}, 1000);

		return () => {
			clearInterval(interval);
		};
	});
</script>

<p>The time is {formatter.format(date)}</p>
class SvelteDate extends Date {}
constructor(...params: any[]);

SvelteMap

一个内置的 Map 对象的响应式版本。通过迭代或通过读取 map.size 或调用 map.get(...)map.has(...)(如下面的 井字棋示例 所示)来读取映射的内容,在 效果派生 中将导致在映射更新时按需重新评估。

请注意,在响应式映射中的值 不是 深度响应的 deeply reactive

<script>
	import { SvelteMap } from 'svelte/reactivity';
	import { result } from './game.js';

	let board = new SvelteMap();
	let player = $state('x');
	let winner = $derived(result(board));

	function reset() {
		player = 'x';
		board.clear();
	}
</script>

<div class="board">
	{#each Array(9), i}
		<button
			disabled={board.has(i) || winner}
			onclick={() => {
				board.set(i, player);
				player = player === 'x' ? 'o' : 'x';
			}}
		>{board.get(i)}</button>
	{/each}
</div>

{#if winner}
	<p>{winner} wins!</p>
	<button onclick={reset}>reset</button>
{:else}
	<p>{player} is next</p>
{/if}
class SvelteMap<K, V> extends Map<K, V> {}
constructor(value?: Iterable<readonly [K, V]> | null | undefined);

set(键: K, 值: V): this;

SvelteSet

一个内置的 Set 对象的响应式版本。通过迭代或通过读取 set.size 或调用 set.has(...)(如下面的 示例 所示)来读取集合的内容,在 效果派生 中将导致在集合更新时根据需要重新评估。

请注意,反应集合中的值 不是 深度反应的 deeply reactive

<script>
	import { SvelteSet } from 'svelte/reactivity';
	let monkeys = new SvelteSet();

	function toggle(monkey) {
		if (monkeys.has(monkey)) {
			monkeys.delete(monkey);
		} else {
			monkeys.add(monkey);
		}
	}
</script>

{#each ['🙈', '🙉', '🙊'] as monkey}
	<button onclick={() => toggle(monkey)}>{monkey}</button>
{/each}

<button onclick={() => monkeys.clear()}>clear</button>

{#if monkeys.has('🙈')}<p>see no evil</p>{/if}
{#if monkeys.has('🙉')}<p>hear no evil</p>{/if}
{#if monkeys.has('🙊')}<p>speak no evil</p>{/if}
class SvelteSet<T> extends Set<T> {}
constructor(value?: Iterable<T> | null | undefined);

add(值: T): this;

SvelteURL

一个内置的URL对象的响应式版本。在效果派生中读取 URL 的属性(如url.hrefurl.pathname)时,如果 URL 发生变化,它将根据需要重新评估。

The searchParams 属性是 SvelteURLSearchParams 的一个实例。

示例

<script>
	import { SvelteURL } from 'svelte/reactivity';

	const url = new SvelteURL('https://example.com/path');
</script>

<!-- changes to these... -->
<input bind:value={url.protocol} />
<input bind:value={url.hostname} />
<input bind:value={url.pathname} />

<hr />

<!-- will update `href` and vice versa -->
<input bind:value={url.href} size="65" />
class SvelteURL extends URL {}
get searchParams(): SvelteURLSearchParams;

SvelteURLSearchParams

一个内置的 URLSearchParams 对象的响应式版本。通过迭代或调用 params.get(...)params.getAll(...)(如下面的 示例 所示)读取其内容,在 效果派生 中将根据参数的更新必要时重新评估。

<script>
	import { SvelteURLSearchParams } from 'svelte/reactivity';

	const params = new SvelteURLSearchParams('message=hello');

	let key = $state('key');
	let value = $state('value');
</script>

<input bind:value={key} />
<input bind:value={value} />
<button onclick={() => params.append(key, value)}>append</button>

<p>?{params.toString()}</p>

{#each params as [key, value]}
	<p>{key}: {value}</p>
{/each}
class SvelteURLSearchParams extends URLSearchParams {}
[REPLACE](params: URLSearchParams): void;

创建订阅者

自 5.7.0 版本起可用

返回一个将外部基于事件的系统与 Svelte 的响应性集成的subscribe函数。它特别适用于与 Web API 如MediaQueryIntersectionObserverWebSocket集成。

如果在内联(包括间接地,例如在 getter 中)调用 subscribe,则将使用 update 函数调用 start 回调。每当调用 update 时,效果将重新运行。

如果start返回一个清理函数,则在效果被销毁时将调用该函数。

如果在一个或多个效果中调用 subscribe,只要效果处于活动状态,start 将只会被调用一次,并且当所有效果被销毁时,返回的 teardown 函数才会被调用。

以示例来理解最为直观。以下是对MediaQuery的一个实现:

import { function createSubscriber(start: (update: () => void) => (() => void) | void): () => void

Returns a subscribe function that, if called in an effect (including expressions in the template), calls its start callback with an update function. Whenever update is called, the effect re-runs.

If start returns a function, it will be called when the effect is destroyed.

If subscribe is called in multiple effects, start will only be called once as long as the effects are active, and the returned teardown function will only be called when all effects are destroyed.

It’s best understood with an example. Here’s an implementation of MediaQuery:

import { createSubscriber } from 'svelte/reactivity';
import { on } from 'svelte/events';

export class MediaQuery {
	#query;
	#subscribe;

	constructor(query) {
		this.#query = window.matchMedia(`(${query})`);

		this.#subscribe = createSubscriber((update) => {
			// when the `change` event occurs, re-run any effects that read `this.current`
			const off = on(this.#query, 'change', update);

			// stop listening when all the effects are destroyed
			return () => off();
		});
	}

	get current() {
		this.#subscribe();

		// Return the current state of the query, whether or not we're in an effect
		return this.#query.matches;
	}
}
@since5.7.0
createSubscriber
} from 'svelte/reactivity';
import { function on<Type extends keyof WindowEventMap>(window: Window, type: Type, handler: (this: Window, event: WindowEventMap[Type]) => any, options?: AddEventListenerOptions | undefined): () => void (+4 overloads)

Attaches an event handler to the window and returns a function that removes the handler. Using this rather than addEventListener will preserve the correct order relative to handlers added declaratively (with attributes like onclick), which use event delegation for performance reasons

on
} from 'svelte/events';
export class class MediaQueryMediaQuery { #query; #subscribe; constructor(query: anyquery) { this.#query = var window: Window & typeof globalThiswindow.function matchMedia(query: string): MediaQueryListmatchMedia(`(${query: anyquery})`); this.#subscribe = function createSubscriber(start: (update: () => void) => (() => void) | void): () => void

Returns a subscribe function that, if called in an effect (including expressions in the template), calls its start callback with an update function. Whenever update is called, the effect re-runs.

If start returns a function, it will be called when the effect is destroyed.

If subscribe is called in multiple effects, start will only be called once as long as the effects are active, and the returned teardown function will only be called when all effects are destroyed.

It’s best understood with an example. Here’s an implementation of MediaQuery:

import { createSubscriber } from 'svelte/reactivity';
import { on } from 'svelte/events';

export class MediaQuery {
	#query;
	#subscribe;

	constructor(query) {
		this.#query = window.matchMedia(`(${query})`);

		this.#subscribe = createSubscriber((update) => {
			// when the `change` event occurs, re-run any effects that read `this.current`
			const off = on(this.#query, 'change', update);

			// stop listening when all the effects are destroyed
			return () => off();
		});
	}

	get current() {
		this.#subscribe();

		// Return the current state of the query, whether or not we're in an effect
		return this.#query.matches;
	}
}
@since5.7.0
createSubscriber
((update: () => voidupdate) => {
// when the `change` event occurs, re-run any effects that read `this.current` const const off: () => voidoff = on<MediaQueryList, "change">(element: MediaQueryList, type: "change", handler: (this: MediaQueryList, event: MediaQueryListEvent) => any, options?: AddEventListenerOptions | undefined): () => void (+4 overloads)

Attaches an event handler to an element and returns a function that removes the handler. Using this rather than addEventListener will preserve the correct order relative to handlers added declaratively (with attributes like onclick), which use event delegation for performance reasons

on
(this.#query, 'change', update: () => voidupdate);
// stop listening when all the effects are destroyed return () => const off: () => voidoff(); }); } get MediaQuery.current: booleancurrent() { // This makes the getter reactive, if read in an effect this.#subscribe(); // Return the current state of the query, whether or not we're in an effect return this.#query.MediaQueryList.matches: booleanmatches; } }
function createSubscriber(
	start: (update: () => void) => (() => void) | void
): () => void;

Edit this page on GitHub llms.txt