Svelte: Как предотвратить обновление блока {#await} при каждом изменении связанного атрибута?

Я пытаюсь инициализировать вход <select/> данными, полученными из функции на основе Promise. После того, как ввод инициализирует параметры (каждая опция получает значение и метку из разрешенных данных), атрибут привязывается к <select/>.

Но каждый раз, когда я меняю параметр (с привязкой атрибута), все внутри блока {#await} перезагружается (похоже, что он разрешает одно и то же обещание и сбрасывает параметры).

Этого не происходит, когда я снимаю привязку.

Я пробовал следующее:

  • Пробовал привязать атрибут к выбранному.

    `<select bind:value={selected_device}>...`
    
  • Пытался привязать событие, которое получает выбранный вариант из списка.

    `<select on:change={set_selected_device}>...`
    
  • Пытался сделать еще одну кнопку, чтобы получить выбранный вариант.

    <select>...</select>
    <button on:click={set_selected_device}>Set</button>`
    

Это фрагмент текущего состояния:

Блок ожидания:

<div class="device-select container">
  {#await VoiceStreamingService.get_microhpones()}

  {:then devices}
    <select id="device-options">
      <option selected disabled>Select an Option...</option>
      {#each devices as device (device.deviceId)}
        <option value={device.deviceId}>{device.label}</option>
      {/each}
    </select>
  {:catch}

  {/await}
  <button on:click={set_selected_device}>Connect To</button>
</div>

Функция set_selected_device:

function set_selected_device() {
    let d = document.getElementById("device-options");
    selected_device = d.options[d.selectedIndex].value;
    console.log(selected_device);
  }

Я упускаю что-то важное или это ошибка?


person Ashik Unni    schedule 05.07.2019    source источник


Ответы (2)


Боюсь, это ошибка: https://github.com/sveltejs/svelte/issues/2355

Обходной путь - создать переменную в вашем скрипте ...

let promise = VoiceStreamingService.get_microhpones();

и ждите этого вместо выражения.

person Rich Harris    schedule 06.07.2019
comment
Спасибо, Рич, за ваше предложение. Я пробовал это. Я отправлю свой ответ. - person Ashik Unni; 07.07.2019

Я попытался разрешить обещание после того, как компонент был смонтирован, а затем отправил параметры в объект выбора.

Совместное использование кода ниже:

onMount(() => {
  (async () => {
    let select = document.getElementById("device-options");
    try {
      (await VoiceStreamingService.get_microhpones()).forEach(device => {
        let option = document.createElement("option");
        option.value = device.deviceId;
        option.innerHTML = device.label;
        select.appendChild(option);
      });
    } catch (e) {
      console.log(e);
    }
  })();
});
person Ashik Unni    schedule 07.07.2019
comment
Лучше использовать привязку данных Svelte, чем запрашивать и манипулировать DOM. Сама функция onMount может быть асинхронной, поэтому вы можете сделать что-то вроде let devices; onMount(async () => devices = await ...) - person Rich Harris; 07.07.2019
comment
Что касается части onMount, то это намного лучше. Но не могли бы вы объяснить привязку данных? Потому что я не мог понять, как привязать разрешенный массив к объекту select. (директива {#each} вызывается до разрешения устройств) - person Ashik Unni; 08.07.2019
comment
Я должен был сказать let devices = []; - т.е. инициализировать его пустым массивом, который заменяется списком устройств после разрешения обещания. - person Rich Harris; 08.07.2019