Skip to main content

上一节中的应用能用,但是有一个小小的 bug:那个 store 被订阅了,但是从没有取消订阅。如果这个组件会被创建和销毁好多次,那么就容易造成 内存泄漏

App.svelte 中声明 unsubscribe

App.svelte
const unsubscribe = count.subscribe((value) => {
	count_value = value;
});

调用 subscribe 方法会返回一个 unsubscribe 函数。

现在有 unsubscribe 了,但还需要调用,比如通过 onDestroy 这个生命周期函数来调用:

App.svelte
<script>
	import { onDestroy } from 'svelte';
	import { count } from './stores.js';
	import Incrementer from './Incrementer.svelte';
	import Decrementer from './Decrementer.svelte';
	import Resetter from './Resetter.svelte';

	let count_value;

	const unsubscribe = count.subscribe(value => {
		count_value = value;
	});

	onDestroy(unsubscribe);
</script>

<h1>The count is {count_value}</h1>

事情开始变得麻烦起来,特别是你的组件需要订阅很多 store 的时候。这里,Svelte 有一个小妙招:你可以通过在 store 的名称前加 $ 来引用 store 中的值:

App.svelte
<script>
	import { onDestroy } from 'svelte';
	import { count } from './stores.js';
	import Incrementer from './Incrementer.svelte';
	import Decrementer from './Decrementer.svelte';
	import Resetter from './Resetter.svelte';

	let count_value;

	const unsubscribe = count.subscribe(value => {
		count_value = value;
	});

	onDestroy(unsubscribe);
</script>

<h1>The count is {$count}</h1>

自动订阅只对在一个组件最顶层范围上声明或导入的 store 变量有用。

$count 的使用不局限在标记代码(markup)中,你也可以在 <script> 标签内的任何地方使用,比如在事件处理器中或者响应式声明中。

任何以 $ 开头的变量都会被默认当作一个 store 变量。因此这算是一个保留字符了,Svelte 会阻止你声明自己的带 $ 前缀的变量。

Next: 可读存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
	import { count } from './stores.js';
	import Incrementer from './Incrementer.svelte';
	import Decrementer from './Decrementer.svelte';
	import Resetter from './Resetter.svelte';
 
	let count_value;
 
	count.subscribe((value) => {
		count_value = value;
	});
</script>
 
<h1>The count is {count_value}</h1>
 
<Incrementer />
<Decrementer />
<Resetter />
 
initialising