Svelte 5中子组件Props无法随父组件状态更新的问题
Svelte 5中子组件Props无法随父组件状态更新的问题
嗨,我来帮你看看这个问题!你遇到的情况确实有点坑,Svelte 5的 reactivity模型和Svelte 4确实有不少变化,刚开始用的时候容易踩坑。
先说说你代码里的问题出在哪:
首先,你用了$derived(items.splice(0,5)),这里有两个关键问题:
- splice的误用:splice是会直接修改原数组的方法,它会把items的前5个元素删掉,这肯定不是你想要的吧?应该用
slice(0,5),这个方法会返回前5个元素的新数组,不会改动原数组。 - $derived和$state.raw的配合问题:你用
$state.raw是想只在赋值时触发 reactivity,这没问题,但$derived在这里可能没有正确追踪到items的赋值变化——或者说,即使它追踪到了,你的写法导致子组件没拿到更新后的值。
再说说为什么父组件更新了子组件没更新:父组件里的items被赋值为API返回的数组,触发了父组件的更新,但你的splitItems是通过$derived生成的,它的更新没有正确传递给子组件。这可能是因为$derived在处理$state.raw变量时,没有把更新传递给子组件的props。
那该怎么改呢?其实很简单,换个思路,不要用$derived,而是在API请求完成后手动给splitItems赋值:
父组件修改后代码:
<script> import Child from "./Child.svelte" import { onMount } from "svelte"; import apireq from "./api.js"; // 用$state.raw确保只有赋值时触发 reactivity,符合你的性能需求 let items = $state.raw([]); let splitItems = $state.raw([]); onMount(() => { apireq().then(v => { items = v; // 用slice获取前5个元素,不修改原数组 splitItems = items.slice(0, 5); }) }) </script> <h1>item count in parent {items.length}</h1> <Child items={splitItems} />
子组件可以简化一下写法,不用先存props变量,直接解构$props()就行:
<script> let { items } = $props(); </script> item count in child: <div>{items.length}</div>
这样改完之后,当API请求完成,items被赋值为新数组,接着splitItems被赋值为前5个元素,splitItems的赋值会触发子组件props的更新,子组件就能正确显示元素数量了。
另外,你提到不想用全量 reactivity,这个写法完全符合你的需求:只有当items或splitItems被重新赋值时才会触发更新,数组内部的mutation不会触发 reactivity,完美适配大数组的场景。
最后,关于Svelte 5的适配,确实需要花点时间适应,毕竟 reactivity模型有不少变化,慢慢摸清楚新的写法就好了。
备注:内容来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

