为何Svelte中对象无法更新?绑定非响应式属性报错
问题原因
$derived的局限性:你用$derived创建的content是派生状态,它会完全依赖changed自动重新计算,本身是只读的;且$derived返回的是普通对象,对象的属性不具备响应式追踪能力,Svelte无法检测到content.one的变化,因此触发binding_property_non_reactive错误。- 冗余的绑定写法:父组件中
bind:content={() => content, (v) => content = v}的自定义getter/setter完全没必要,反而会因为尝试给只读的$derived赋值导致逻辑混乱,无法正确更新状态。
解决办法
1. 将content改为响应式状态对象
把$derived替换为$state,让content成为可修改的响应式对象,初始值沿用你原本的推导逻辑:
<!-- App.svelte --> <script> import Form from "./Form.svelte"; let changed = $state(false); // 用$state创建响应式对象,初始值基于changed生成 let content = $state({one: `hello ${changed}`, two: changed }); </script> <!-- 直接使用bind:content即可,无需自定义getter/setter --> <Form bind:content />
2. (可选)同步changed对content的影响
如果希望changed的值变化时,content能同步更新初始逻辑(比如hello ${changed}),可以添加$effect监听changed的变化:
<!-- App.svelte 新增$effect逻辑 --> <script> import Form from "./Form.svelte"; let changed = $state(false); let content = $state({one: `hello ${changed}`, two: changed }); // 当changed变化时,更新content的对应属性 $effect(() => { content.one = `hello ${changed}`; content.two = changed; }); </script> <Form bind:content />
3. 子组件保持原有逻辑
子组件代码无需修改,现在content是响应式状态对象,content.one具备响应式追踪能力,绑定不会再报错:
<!-- Form.svelte --> <script> let { content = $bindable() } = $props(); </script> <input type="text" bind:value={content.one} />
修改后,输入框的变化会同步更新父组件的content,同时changed变化时也能自动更新content的对应属性(若添加了$effect)。
内容的提问来源于stack exchange,提问作者Fred Hors
相关产品推荐
相关产品推荐

