Привязка ввода Svelte прерывается, когда реактивное значение является ссылочным типом? - PullRequest
1 голос
/ 24 марта 2020

(я новичок в Svelte, поэтому вполне вероятно, что я здесь что-то не так делаю)

ОБНОВЛЕНИЕ: я добавил вторую, немного другую REPL, который может продемонстрировать проблему лучше. Попробуйте это: https://svelte.dev/repl/ad7a65894f8440ad9081102946472544?version=3.20.1


Я столкнулся с проблемой при попытке привязать ввод текста к реактивному значению.

I ' Я изо всех сил пытаюсь описать проблему словами, поэтому, надеюсь, уменьшенная демонстрация проблемы в прилагаемом 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>

Таким образом, нажатие кнопки «Один» устанавливает ввод текста на «один», а нажатие кнопки «Два» устанавливает поле ввода на «два».

Важно отметить, что вы все равно можете ввести что-либо в поле ввода .


Второй комп. nent передается два массива значений:

<Selector valueOne={[1, "one"]} valueTwo={[2, "two"]}/>

Снова при нажатии кнопок устанавливается selectedValue на один из них.

Однако на этот раз объявление реактивной зависит от элемент массива:

$: value = selectedValue[1]

Все работает как прежде, кроме того, что теперь вы больше не можете вводить в поле ввода вообще .

Так что вопрос - почему <input bind:value> ведет себя по-разному для этих двух:

$: value = aString

против

$: value = anArray[x]

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Кажется, что это проблема только при использовании двусторонних привязок.

При переключении на односторонний и входной обработчик on: проблема исчезает:

т.е. вместо этого:

<input type="text" bind:value={valX}/>

используйте это:

<input type="text" value={valX} on:input={e => valX = e.target.value}/>
0 голосов
/ 25 марта 2020

Я почти уверен, что ваша реактивная декларация перезаписывает ваше связанное значение, как только оно изменится, что происходит при каждом нажатии клавиши на входе и каждом нажатии кнопки. То есть технически это работает, вы просто возвращаете его каждый раз, когда оно меняется. Посмотрите эту версию , в которой используется наблюдатель.

Кроме того, привязка к реактивному объявлению означает, что вы фактически никогда не меняете переменные с помощью ввода (что вы можете увидеть в вашем 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>

. Привязка напрямую к выбранному значению или его индексу дополнительное преимущество изменения значения с помощью ввода. Вот рабочий пример в REPL

...