在Svelte项目里,组件化开发不可避免会带来状态放在哪里、怎么让多个组件拿到同一份数据并且自动刷新的问题。Svelte的设计理念和框架如React不同,它把很多响应式逻辑编译成了高效的原生JS,理解清楚同步方式能少写很多样板代码。

使用props和事件做父子同步
最常见的场景是父组件向子组件传数据,子组件内部改动后通知父组件。父组件通过属性传递,子组件用export_let接收,注意这里在代码里实际是export let,只是术语展示转义。子组件使用createEventDispatcher发出事件。
<!-- Parent.svelte -->
<script>
import Child from './Child.svelte';
let count = 0;
function handleAdd(e) {
count = e.detail;
}
</script>
<Child {count} on:add={handleAdd} />
<p>父组件中的 count: {count}</p>
<!-- Child.svelte -->
<script>
import { createEventDispatcher } from 'svelte';
export let count;
const dispatch = createEventDispatcher();
function add() {
const next = count + 1;
dispatch('add', next);
}
</script>
<button on:click={add}>子组件加一</button>
<p>子组件收到的 count: {count}</p>
用store处理跨组件全局状态
当状态需要在没有直接父子关系的组件间共享时,Svelte的store是很好的选择。writable创建一个可写store,任何组件都能订阅它,也能修改它,所有订阅者都会响应式更新。
// store.js
import { writable } from 'svelte/store';
export const user = writable({ name: '访客', loggedIn: false });
// 修改状态
user.set({ name: '小李', loggedIn: true });
user.update(u => ({ ...u, name: '小王' }));
在组件中使用store时,前面加$符号就能自动订阅,框架会帮你处理订阅和销毁。
<!-- Profile.svelte -->
<script>
import { user } from './store.js';
</script>
<p>当前用户: {$user.name}</p>
<p>登录状态: {$user.loggedIn}</p>
响应式语句的使用
Svelte里用$:标记响应式语句,当依赖的变量变化时会重新执行。注意不要写成标签形式,它只是语言层面的语法。
<script>
let a = 1;
let b = 2;
$: sum = a + b;
$: console.log('sum 变成了', sum);
</script>
常见更新不生效的原因
- 直接给数组或对象赋值索引或属性,Svelte无法侦测,要用重新赋值的方式。
- store忘记用
$前缀,导致没有订阅。 - 在异步回调里改状态但没触发赋值,可手动调用store的set或update。
| 场景 | 推荐方式 |
|---|---|
| 父子直接传递 | props加事件 |
| 跨级或多组件共享 | writable store |
| 派生状态 | derived store或响应式语句 |
小结
掌握Svelte的组件间状态同步与响应式更新,核心是根据关系远近选props还是store,并遵循它的赋值规则。这样页面数据流动清晰,也不会出现点了没反应的尴尬情况。