Skip to main content
基本 Svelte
介绍
反应性
属性
逻辑
事件
绑定
类和样式
动作
转换
高级 Svelte
高级反应性
重用内容
运动
高级绑定
高级转换
上下文 API
特殊元素
<script module>
后续步骤
基本 SvelteKit
介绍
路由
加载数据
标题和 cookie
共享模块
表单
API 路由
$app/state
错误和重定向
高级 SvelteKit
钩子
页面选项
链接选项
高级路由
高级加载
环境变量
结论

当你需要验证数据时,类特别有用。对于这个 Box 类,不应该能够继续扩大到滑块允许的最大值,但这正是发生的事情。

¥Classes are particularly useful when you need to validate data. In the case of this Box class, it shouldn’t be possible to keep embiggening past the maximum allowed by the sliders, but that’s exactly what happens.

我们可以通过用 getter 和 setter(也称为访问器)替换 widthheight 来解决这个问题。首先,将它们转换为 私有属性

¥We can fix that by replacing width and height with getters and setters, otherwise known as accessors. First, convert them to private properties:

App
class Box {
	#width = $state(0);
	#height = $state(0);
	area = $derived(this.#width * this.#height);

	constructor(width, height) {
		this.#width = width;
		this.#height = height;
	}

	// ...
}

然后,创建一些 getter 和 setter:

¥Then, create some getters and setters:

App
class Box {
	// ...

	get width() {
		return this.#width;
	}

	get height() {
		return this.#height;
	}

	set width(value) {
		this.#width = value;
	}

	set height(value) {
		this.#height = value;
	}

	embiggen(amount) {
		this.width += amount;
		this.height += amount;
	}
}

最后,将验证添加到 setter:

¥Finally, add the validation to the setters:

App
set width(value) {
	this.#width = Math.max(0, Math.min(MAX_SIZE, value));
}

set height(value) {
	this.#height = Math.max(0, Math.min(MAX_SIZE, value));
}

现在,无论你按下按钮的力度有多大,都不可能将框大小增加到安全限制以下,无论是通过范围输入上的 bind:value,还是 embiggen 方法。

¥It’s now impossible to increase the box size past safe limits, whether through the bind:value on the range inputs, or the embiggen method, no matter how hard you press the button.

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
<script>
	const MAX_SIZE = 200;
 
	class Box {
		width = $state(0);
		height = $state(0);
		area = $derived(this.width * this.height);
 
		constructor(width, height) {
			this.width = width;
			this.height = height;
		}
 
		embiggen(amount) {
			this.width += amount;
			this.height += amount;
		}
	}
 
	const box = new Box(100, 100);
</script>
 
<label>
	<input type="range" bind:value={box.width} min={0} max={MAX_SIZE} />
	{box.width}
</label>
 
<label>
	<input type="range" bind:value={box.height} min={0} max={MAX_SIZE} />
	{box.height}
</label>
 
<button onclick={() => box.embiggen(10)}>embiggen</button>
 
<hr>
 
<div
	class="box"
	style:width="{box.width}px"
	style:height="{box.height}px"
>
	{box.area}
</div>
 
<style>
	label {
		display: flex;
		align-items: center;
	}
 
	hr {
		margin: 1em 0;
		border: none;
		border-bottom: 1px solid #888;
	}
 
	.box {
		background: radial-gradient(at 25% 25%, hsl(15 100 60), hsl(15 100 50)) ;
		border-radius: 2px;
		filter: drop-shadow(0 0 10px hsl(15 100 50 / 0.3));
		display: flex;
		align-items: center;
		justify-content: center;
		overflow: hidden;
	}
</style>