Svelte 的响应式赋值到底怎么触发更新的?

设计师爱娜 阅读 15

我刚从 Vue 转过来学 Svelte,有点搞不懂它的响应式机制。在 Vue 里我习惯用 this.count++ 或者 Object.assign 来触发更新,但在 Svelte 里好像直接写 count++ 就行?可我试了下数组操作,发现有时候视图没更新,是不是必须用重新赋值才行?比如下面这种 Vue 写法:

<template>
  <div>{{ list.length }}</div>
</template>

<script>
export default {
  data() {
    return { list: [1, 2] }
  },
  mounted() {
    this.list.push(3) // Vue 能响应
  }
}
</script>

那在 Svelte 里,如果我写 list.push(3) 是不是就没反应?必须写成 list = [...list, 3] 才行?这背后的原理到底是啥?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
Code°东景
Svelte 的响应式机制跟 Vue 完全是两套思路,你搞不懂很正常。

Vue 2 用 Object.defineProperty 劫持属性的 getter/setter,Vue 3 用 Proxy,所以对数组的 push、splice 这些方法能自动拦截到。但 Svelte 不一样,它是在编译阶段分析你的赋值语句,然后自动 inject 更新代码。

简单说:Svelte 的响应式靠的是赋值操作。你写 count++ 本质上就是 count = count + 1,这触发更新没问题。但 list.push(3) 只是调用了一个方法改了数组内容,编译器没看到赋值语句,它就不生成更新代码。

所以你的理解是对的,在 Svelte 里必须这么写:

let list = [1, 2];

function addItem() {
list.push(3); // 这样没用,视图不会更新
list = [...list, 3]; // 这样才触发更新
}

// 或者用其他方式强制赋值
list = list; // 也能触发,但有点 hack
list = [...list]; // 这种也行


背后原理是这样的:Svelte 编译 script 块的时候,会记录所有赋值语句的左侧变量。比如它看到 count = xxx,就会在赋值后安排一次 "check if changed, if so notify"。但 push 方法调用不产生赋值,所以它不知道该通知谁。

性能上其实 Svelte 这种设计更利索,Vue 那种拦截方法的方式多少有点额外开销,而且有些边界情况容易踩坑。Svelte 要求你明确用赋值来"声明"状态变化,某种程度上是更可控的。

习惯了就好了,写 Svelte 的时候脑子里要想着"凡改动必赋值",别像 Vue 那样想着"我改了就完事儿"。
点赞
2026-03-19 11:01