Svelte基础
Svelte高阶
上下文API
特殊元素
接下来
SvelteKit基础
Shared modules
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion
在需要做些校验时特别适合使用Class。 比如Class Box
, 我们需要限制它能被放大到的最大值。可以通过把width
和height
属性替换为对应的 get 和 set 方法, 这些方法也被称为存取器。首先我们需要先把属性变为[私有的]
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties):
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. We can fix that by replacingwidth
andheight
with getters and setters, otherwise known as accessors. First, convert them to private properties:
class Box {
#width = $state(0);
#height = $state(0);
area = $derived(this.#width * this.#height);
constructor(width, height) {
this.#width = width;
this.#height = height;
}
// ...
}
然后添加对应的set和get方法:
Then, create some getters and setters:
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;
}
}
最后在set方法中添加校验代码:
Finally, add the validation to the setters:
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 theembiggen
method, no matter how hard you press the button.
<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>