Как вызвать реакцию при связывании: это используется в {#await} в Svelte? - PullRequest
0 голосов
/ 04 октября 2019

Допустим, я хочу иметь небольшой оверлей UI, который указывает на элемент DOM (назовем его «Tap Here»). Чтобы получить местоположение, на которое он должен указывать: я использую bind: это и работает, если только я не использую его в {#await}.

<script>
    import TapHere from './TapHere.svelte';
    let enableButton;
    $: enableButtonRect = enableButton && enableButton.getBoundingClientRect();

    let promise = new Promise((resolve) => {
        setInterval(resolve, 3000);
    });
</script>

{#await promise}
<p>
    waiting...
</p>
{:then}
<div>
  <button bind:this={enableButton}>Enable</button>
  <button>Disable</button>
  <TapHere rect={enableButtonRect}/>
</div>
{/await}

https://svelte.dev/repl/4e0e477d6a394a83a2d79b3d1fa50525?version=3.12.1

(enableButtonRect может быть немного красной селедкой, так как эта проблема проявляется в простой попытке передать сам enableButton в TapHere.) Если вы удаляете await, TapHere переходит в предполагаемое место;но с ожиданием, TapHere не запускается изменением enableButtonRect. Что мне здесь делать?

1 Ответ

1 голос
/ 04 октября 2019

Почему-то enableButton равно undefined в блоке разрешения обещания даже после разрешения обещания.

Однако, если вы оцениваете enableButton вне блока , это правильно undefined, пока обещание все еще находится на рассмотрении, и правильно установлено на [object HTMLButtonElement], как только обещание разрешается.

Должно быть объяснение этому поведению, но я его не знаю. Надеемся, что кто-то может уточнить.

Таким образом, вы можете достичь желаемого результата, переместив компонент <TapHere> за пределы блока обещаний:

<script>
  import TapHere from './TapHere.svelte';
  let enableButton;
  $: enableButtonRect = enableButton && enableButton.getBoundingClientRect();

  let promise = new Promise((resolve) => {
    setInterval(resolve, 3000);
  });
</script>

{#await promise}
<p>
  waiting...
</p>
{:then}
<div>
  <button bind:this={enableButton}>Enable</button>
  <button>Disable</button>
</div>
<p>Inside promise resolve block: {enableButton}</p>
{/await}
<p>Outside promise resolve block: {enableButton}</p>
<TapHere rect={enableButtonRect}/>

Редактировать

Чтобы показатьВо всплывающей подсказке после разрешения обещания вы можете сделать следующее:

<script>
  import { onMount } from 'svelte';
  import TapHere from './TapHere.svelte';
  let enableButton;
  let disabled = true;
  $: enableButtonRect = enableButton && enableButton.getBoundingClientRect() && !disabled;

  onMount(() => {
    const interval = setInterval(() => { disabled = false }, 3000)
    return () => clearInterval(interval)
  })
</script>

<div>
  <button bind:this={enableButton} {disabled}>Enable</button>
  <button>Disable</button>
  <TapHere rect={enableButtonRect}/>
</div>

(REPL обновлено)

https://svelte.dev/repl/e647bc2b1a024e8885ebb96317887710?version=3.12.1

...