在之前的练习中,我们了解到状态是 深度响应 — 如果你(例如)更改对象的属性或推送到数组,它将导致 UI 更新。这通过创建一个拦截读取和写入的 proxy 来实现。
¥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.
有时,这不是你想要的。如果你不更改单个属性,或者保持引用相等很重要,那么你可以改用原始状态。
¥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.
在此示例中,我们有一张 Svelte 稳步上涨的股价图表。我们希望图表在有新数据时更新,我们可以通过将 data 转换为状态来实现...
¥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...
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:
let data = $state.raw(poll());修改原始状态不会产生直接影响。通常,强烈不建议修改非响应式状态。
<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>