Svelte子组件响应式语句异常触发致输入失效求助
问题原因
你遇到的问题核心在于响应式语句的执行逻辑:
- 子组件里的
$: name = person.name;是一条响应式赋值语句,作用是每当依赖的person.name发生变化时,就会重新将name设置为person.name的值。 - 当你绑定输入框到
name后,每次输入修改name时,输入操作会触发组件更新,此时这条响应式语句会被重新执行——由于父组件的person.name始终是空字符串,刚输入的name会立刻被重置为空,导致输入框始终无法输入内容。
解决方案
结合你“不想直接修改父组件对象,通过事件传递数据”的需求,提供两种可行方案:
方案1:仅初始化name,不做持续同步
如果不需要父组件的person.name变化时同步子组件的name,直接去掉响应式语句,只做初始化赋值:
<!-- 子组件 Child.svelte --> <script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); export let person; // 仅初始化name为person.name,后续不再自动同步 let name = person.name; // 输入变化时触发事件通知父组件 function handleInput() { dispatch('update-name', name); } </script> <input bind:value={name} on:input={handleInput} />
父组件接收事件并更新person:
<!-- 主页面 --> <script> import Child from "./Child.svelte"; let person = { name: "" }; function updatePersonName(newName) { // 可在此添加校验等额外逻辑 person = { ...person, name: newName }; } </script> <Child {person} on:update-name={e => updatePersonName(e.detail)} />
方案2:保留父到子的同步,同时通过事件更新父组件
如果需要父组件的person.name变化时,子组件的name也同步更新,同时输入时通过事件通知父组件修改person.name,避免响应式语句的冲突:
<!-- 子组件 Child.svelte --> <script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); export let person; let name; // 当person.name变化时,同步更新子组件的name $: name = person.name; // 输入时触发事件,让父组件更新person.name function handleInput() { dispatch('update-name', name); } </script> <input bind:value={name} on:input={handleInput} />
父组件接收事件更新person的逻辑同方案1:
<!-- 主页面 --> <script> import Child from "./Child.svelte"; let person = { name: "" }; function updatePersonName(newName) { person = { ...person, name: newName }; } </script> <Child {person} on:update-name={e => updatePersonName(e.detail)} />
这种情况下,输入时子组件的name变化会触发父组件更新person.name,此时响应式语句执行时person.name已经是新输入的值,不会出现重置问题。
内容的提问来源于stack exchange,提问作者Titouan Bizet
相关产品推荐
相关产品推荐

