You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Svelte中对象无法更新?绑定非响应式属性报错

问题原因
  1. $derived的局限性:你用$derived创建的content是派生状态,它会完全依赖changed自动重新计算,本身是只读的;且$derived返回的是普通对象,对象的属性不具备响应式追踪能力,Svelte无法检测到content.one的变化,因此触发binding_property_non_reactive错误。
  2. 冗余的绑定写法:父组件中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:33:11