当反应值是引用类型时,Svelte 输入绑定会中断?
Svelte input binding breaks when a reactive value is a reference type?
(我是 Svelte 的新手,所以很可能我在这里做错了什么)
更新:我添加了第二个略有不同的 REPL,它可以更好地说明问题。试试这个: https://svelte.dev/repl/ad7a65894f8440ad9081102946472544?version=3.20.1
我在尝试将文本输入绑定到反应值时遇到问题。
我很难用语言来描述这个问题,所以希望在随附的 REPL 中简化这个问题的演示会更有意义。
https://svelte.dev/repl/6c8068ed4cc048919f71d87f9d020696?version=3.20.1
该演示在页面上包含两个自定义 <Selector>
组件。
第一个组件传递了两个 string 值("one" 和 "two"):
<Selector valueOne="one" valueTwo="two"/>
单击输入字段旁边的按钮将 selectedValue
设置为这些值之一。
这反过来会触发以下响应式声明进行更新:
$: value = selectedValue
输入字段绑定到这个反应值:
<input type="text" bind:value>
因此单击 "One" 按钮将输入文本设置为 "one",单击 "Two" 按钮将输入字段设置为 "two"。
但重要的是,您仍然可以在输入字段中输入任何内容。
第二个组件传递了两个数组值:
<Selector valueOne={[1, "one"]} valueTwo={[2, "two"]}/>
同样,单击按钮将 selectedValue
设置为其中之一。
然而这次响应式声明依赖于一个数组元素:
$: value = selectedValue[1]
一切都像以前一样工作,除了现在 您根本无法再在输入字段中输入内容。
所以问题是 - 为什么 <input bind:value>
对这两个行为不同:
$: value = aString
对
$: value = anArray[x]
我很确定你的反应式声明会在你的绑定值发生变化时覆盖它,这是在输入的每一次击键和每一次按钮按下时发生的。这意味着它在技术上是有效的,你只是在每次更改时恢复它。查看 this version 个使用观察器的。
同时绑定到反应式声明意味着您实际上永远不会使用输入更改变量(当您输入输入时,您可以在第一个选择器的 JSON 结果中看到该值不'仅在单击按钮时更新)。
为什么不丢掉响应式声明,直接绑定到你想要的变量。然后使用 {#if}
块根据 index
?
的真实性在您显示的输入版本之间切换
<script>
export let valueOne;
export let valueTwo;
export let index;
let selectedValue = index? [] : '';
let selectValue = (val) => selectedValue = val;
</script>
{#if index}
<input type="text" bind:value={selectedValue[index]} placeholder="Type anything...">
{:else}
<input type="text" bind:value={selectedValue} placeholder="Type anything...">
{/if}
<button on:click={() => selectValue(valueOne)}>One</button>
<button on:click={() => selectValue(valueTwo)}>Two</button>
<p>
<strong>Selected value:</strong> {JSON.stringify(selectedValue)}
</p>
通过直接绑定到 selectedValue 或其索引,您可以获得使用输入更改值的额外好处。这是 REPL
中的一个工作示例
似乎只有在使用双向绑定时才会出现这个问题。
通过切换到单向处理程序和 on:input 处理程序,问题就消失了:
即而不是这个:
<input type="text" bind:value={valX}/>
使用这个:
<input type="text" value={valX} on:input={e => valX = e.target.value}/>
(我是 Svelte 的新手,所以很可能我在这里做错了什么)
更新:我添加了第二个略有不同的 REPL,它可以更好地说明问题。试试这个: https://svelte.dev/repl/ad7a65894f8440ad9081102946472544?version=3.20.1
我在尝试将文本输入绑定到反应值时遇到问题。
我很难用语言来描述这个问题,所以希望在随附的 REPL 中简化这个问题的演示会更有意义。
https://svelte.dev/repl/6c8068ed4cc048919f71d87f9d020696?version=3.20.1
该演示在页面上包含两个自定义 <Selector>
组件。
第一个组件传递了两个 string 值("one" 和 "two"):
<Selector valueOne="one" valueTwo="two"/>
单击输入字段旁边的按钮将 selectedValue
设置为这些值之一。
这反过来会触发以下响应式声明进行更新:
$: value = selectedValue
输入字段绑定到这个反应值:
<input type="text" bind:value>
因此单击 "One" 按钮将输入文本设置为 "one",单击 "Two" 按钮将输入字段设置为 "two"。
但重要的是,您仍然可以在输入字段中输入任何内容。
第二个组件传递了两个数组值:
<Selector valueOne={[1, "one"]} valueTwo={[2, "two"]}/>
同样,单击按钮将 selectedValue
设置为其中之一。
然而这次响应式声明依赖于一个数组元素:
$: value = selectedValue[1]
一切都像以前一样工作,除了现在 您根本无法再在输入字段中输入内容。
所以问题是 - 为什么 <input bind:value>
对这两个行为不同:
$: value = aString
对
$: value = anArray[x]
我很确定你的反应式声明会在你的绑定值发生变化时覆盖它,这是在输入的每一次击键和每一次按钮按下时发生的。这意味着它在技术上是有效的,你只是在每次更改时恢复它。查看 this version 个使用观察器的。
同时绑定到反应式声明意味着您实际上永远不会使用输入更改变量(当您输入输入时,您可以在第一个选择器的 JSON 结果中看到该值不'仅在单击按钮时更新)。
为什么不丢掉响应式声明,直接绑定到你想要的变量。然后使用 {#if}
块根据 index
?
<script>
export let valueOne;
export let valueTwo;
export let index;
let selectedValue = index? [] : '';
let selectValue = (val) => selectedValue = val;
</script>
{#if index}
<input type="text" bind:value={selectedValue[index]} placeholder="Type anything...">
{:else}
<input type="text" bind:value={selectedValue} placeholder="Type anything...">
{/if}
<button on:click={() => selectValue(valueOne)}>One</button>
<button on:click={() => selectValue(valueTwo)}>Two</button>
<p>
<strong>Selected value:</strong> {JSON.stringify(selectedValue)}
</p>
通过直接绑定到 selectedValue 或其索引,您可以获得使用输入更改值的额外好处。这是 REPL
中的一个工作示例似乎只有在使用双向绑定时才会出现这个问题。
通过切换到单向处理程序和 on:input 处理程序,问题就消失了:
即而不是这个:
<input type="text" bind:value={valX}/>
使用这个:
<input type="text" value={valX} on:input={e => valX = e.target.value}/>