Skip to main content

响应式 $: 语句

在符文模式下,对状态更新的响应是通过 $derived$effect 符文来处理的。

在遗留模式下,任何顶层语句(即不在代码块或函数内部的语句)都可以通过在其前面加上 $: 标签使其具有响应式。这些语句在 <script> 中的其他代码之后、组件标记渲染之前运行,然后在它们依赖的值发生变化时重新运行。

<script>
	let a = 1;
	let b = 2;

	// 这是一个'响应式语句',当 `a`、`b` 或 `sum`
	// 发生变化时它会重新运行
	$: console.log(`${a} + ${b} = ${sum}`);

	// 这是一个'响应式赋值'—— 当 `a` 或 `b` 发生变化时
	// `sum` 将被重新计算。不需要单独声明 `sum`
	$: sum = a + b;
</script>

语句按照它们的依赖关系和赋值进行拓扑排序:由于 console.log 语句依赖于 sum,所以即使 sum 在源代码中出现较后,它也会先被计算。

多个语句可以通过将它们放在一个块中来组合:

$: {
	// 当 `items` 发生变化时重新计算 `total`
	total = 0;

	for (const const item: anyitem of items) {
		total += const item: anyitem.value;
	}
}

响应式赋值的左侧可以是一个标识符,也可以是一个解构赋值:

$: ({ larry: anylarry, moe: anymoe, curly: anycurly } = stooges);

理解依赖关系

$: 语句的依赖关系是在编译时确定的 —— 它们是在语句内部被引用(但未被赋值)的任何变量。

换句话说,当 count 改变时,像这样的语句将不会重新运行,因为编译器无法”看到”依赖关系:

let let count: numbercount = 0;
let let double: () => numberdouble = () => let count: numbercount * 2;

$: doubled = let double: () => numberdouble();

同样,如果依赖关系是间接引用的,拓扑排序将会失败:z 永远不会更新,因为在更新发生时 y 不被视为”dirty”。将 $: z = y 移到 $: setY(x) 下面将修复这个问题:

<script>
	let x = 0;
	let y = 0;

	$: z = y;
	$: setY(x);

	function setY(value) {
		y = value;
	}
</script>

仅浏览器代码

响应式语句在服务端渲染和浏览器中都会运行。这意味着任何只应在浏览器中运行的代码都必须包装在 if 块中:

$: if (browser) {
	var document: Documentdocument.Document.title: string

Contains the title of the document.

MDN Reference

title
= title;
}

在 GitHub 编辑此页面