Skip to main content
Svelte基础
介绍
响应
属性Props
逻辑表达式
事件
绑定
Classes和样式
动作Actions
转场
Svelte高阶
响应式进阶
内容复用
动画
高级绑定
高级转场
上下文API
特殊元素
脚本模块
接下来
SvelteKit基础
介绍
路由
加载数据
Headers和cookies
Shared modules
Forms
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Hooks
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion

恭喜小主,开启了高级功法💕💕💕 在先前的练习中我们学到状态是深度响应的——当修改一个对象的某个属性或者往数组中添加元素时都会引起UI更新。这是通过创建代理拦截读写操作实现的。

In previous exercises, we learned that state is deeply reactive — if you (for example) change a property of an object, or push to an array, it will cause the UI to update. This works by creating a proxy that intercepts reads and writes.

有时候这可能不是你想要的。比如你并不想修改某个属性或者需要保持引用相等,这个时候你可以使用 raw状态 。 不愧是高阶功法,就是拗口, 没点悟性和耐心还真参悟不了。 也就是只在用新状态替换原来的状态时才更新UI,我们就不需要通过 修改 原状态更新UI。 举个栗子🌰: 做一个持续显示股票价格的图表(曲线图)。只有当获取到新数据时才更新图表:

Occasionally, that’s not what you want. If you’re not changing individual properties, or if it’s important to maintain referential equality, then you can use raw state instead. In this example, we have a chart of Svelte’s steadily increasing stock price. We want the chart to update when new data comes in, which we could achieve by turning data into state...

App
let data = $state(poll());

虽然也能达到效果,但勤俭持家的小主是不是觉得有点浪费了, 毕竟这里使用深度响应是没有意义的,因为新数据很快就会到,原来的数据也很快会被丢弃。可以使用$state.raw:

...but there’s no need to make it deeply reactive when it will be discarded a few milliseconds later. Instead, use $state.raw:

App
let data = $state.raw(poll());

修改Raw状态是没有效应的. 通常我们也不应该不推荐修改非响应状态。

Mutating raw state will have no direct effect. In general, mutating non-reactive state is strongly discouraged.

Edit this page on GitHub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<script>
	import { scale } from './utils.js';
	import { poll } from './data.js';
 
	let data = poll();
 
	let w = $state(1);
	let h = $state(1);
 
	const min = $derived(Math.min(...data) - 5);
	const max = $derived(Math.max(...data) + 5);
	const x = $derived(scale([0, data.length], [0, w]));
	const y = $derived(scale([min, max], [h, 0]));
 
	const ticks = $derived.by(() => {
		const result = [];
		let n = 10 * Math.ceil(min / 10);
		while (n < max) {
			result.push(n);
			n += 10;
		}
		return result;
	});
 
	$effect(() => {
		const interval = setInterval(() => {
			data = poll();
		}, 200);
 
		return () => {
			clearInterval(interval);
		};
	});
</script>
 
<div class="outer">
	<svg width={w} height={h} bind:clientWidth={w} bind:clientHeight={h}>
		<line y1={h} y2={h} x2={w} />
 
		{#each ticks as tick}
			<g class="tick" transform="translate(0,{y(tick)})">
				<line x2={w} />
				<text x={-5}>{tick}</text>
			</g>
		{/each}
 
		<polyline points={data.map((d, i) => [x(i), y(d)]).join(' ')} />
 
		<text x={10} y={10} font-size={36}>$SVLT</text>
	</svg>
</div>
 
<style>
	.outer {
		width: 100%;
		height: 100%;
		padding: 2em;
		box-sizing: border-box;
	}
 
	svg {
		width: 100%;
		height: 100%;
		overflow: visible;
	}
 
	polyline {
		fill: none;
		stroke: #ff3e00;
		stroke-width: 2;
		stroke-linejoin: round;
		stroke-linecap: round;
	}
 
	line {
		stroke: #aaa;
	}
 
	.tick {
		stroke-dasharray: 2 2;
 
		text {
			text-anchor: end;
			dominant-baseline: middle;
		}
	}
</style>