DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Svelte 5 bind:value 报 props_invalid_value:父级初值 undefined

有fallback的bindable绑定要求父级初值非undefined。明确文本默认值或支持缺失值的组件契约,检查回填、重置和初始化阶段。

子组件写了 value = $bindable(''),父组件用 bind:value 绑定一个初始 undefined 的变量,页面报 props_invalid_value,提示不能给有 fallback 的 value 绑定 undefined。先检查父级实际值:子组件的 fallback 不会自动替父组件初始化这份绑定状态。

这是 Svelte 5 runes 模式的约定,当前 5.57.2 仍保留。父子绑定需要使用一致的值;不能照搬 Svelte 4 把子组件默认值回写给父组件的行为。

文本字段在父级明确初始化

如果业务把空文本表示为 '',父级也用这个值初始化。以下是对应的两个组件:

<!-- Input.svelte -->
<script>
  let { value = $bindable('') } = $props();
</script>

<input type="text" bind:value />
<!-- App.svelte -->
<script>
  import Input from './Input.svelte';

  let value = $state('');
</script>

<Input bind:value />
<p>{value}</p>

父级绑定的是已经存在的字符串,后续输入按同一份绑定状态更新。数字、可选项、缺失字段有各自的业务含义,不能把所有 undefined 都替换成空字符串。

如果表单绑定 form.password,检查加载、回填与 reset 是否保留这个字段。接口省略密码可能是有意的契约,不代表页面可以将空字符串原样提交覆盖已有密码;表单初值与提交时是否包含该字段需要分别定义。

允许 undefined 时,先重新定义组件契约

组件本来就允许 undefined,可以评估不提供 fallback:

let { value = $bindable() } = $props();

去掉 fallback 只取消这项初始化冲突,并不替组件实现缺失值显示、校验和提交行为。内部 input、格式化代码与事件处理都必须能够接受新的值范围。

没有使用 bind 的父级可以不给 prop,由子组件使用 fallback。单向传值与双向绑定不是同一个初始化场景;不要把它们在一次测试中混为一谈。

后续变化不等于初始化规则失效

某段代码能在挂载后赋 undefined,不足以证明初始化时也允许 undefined 与非空 fallback 同时绑定。当前运行时的冲突检查位于 prop 初始化阶段,后续 getter 又可能取 fallback,导致父子看到不同值。

比较示例时还要检查子组件是不是已经从 $bindable('') 改成了 $bindable()。fallback 被移除,当然不能再作为“同样 fallback 允许 undefined”的证据。

不必给每个字段增加 $effect,反复把 undefined 改回默认值。它可能覆盖加载或 reset 过程中的合法状态,还让初始化发生额外一轮更新。先在拥有状态的父级或受控数据入口定义默认值,确实需要缺失值时则明确支持它。

验证首次挂载、数据晚到、用户编辑与重置,检查父级状态、子级显示及提交数据一致;同时检查未绑定调用方的 fallback。恢复旧代码时,保留已经输入的表单数据,不能只为压掉错误而清空整个模型。