Подождите, пока компонент будет готов, в настраиваемой директиве svelte

Недавно я попытался написать специальную директиву, которая выполняла некоторую логику и отправляла событие обратно тому элементу, в котором оно использовалось.

//svelte file
<div use:customDiective on:success={handleSuccess}>...</div>
// Custom directive
export const customDirective = node => {
    //some synchronous logic here

    node.dispatchEvent(new CustomEvent('success', node))
}

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


person Mats    schedule 20.05.2021    source источник
comment
Вы можете использовать Promise для подготовки состояния узла и вызвать его метод .then () для отправки вашего настраиваемого события.   -  person Lajos Arpad    schedule 20.05.2021


Ответы (1)


Вы можете использовать функцию жизненного цикла onMount внутри своего действия:

// directive.js
import { onMount } from 'svelte';

export const customDirective = (node) => {
    onMount(() => {
        // other logic
        node.dispatchEvent(new CustomEvent('success', node));
    });     
}
<!-- App.svelte -->
<script>
    import { customDirective } from './directive.js';
    
    let isSuccess = false;
</script>

<div use:customDirective on:success={() => (isSuccess = true)}>{isSuccess}</div>

В качестве альтернативы, если вы поместите директиву on: перед директивой use:, прослушиватель событий будет настроен перед запуском действия.

<div on:success={() => (isSuccess = true)} use:customDirective>{isSuccess}</div>

Вы можете увидеть порядок директив в сгенерированном коде Svelte:

// on: before use:
if (!mounted) {
    dispose = [
        listen(div, "success", /*success_handler*/ ctx[1]),
        action_destroyer(customDirective_action = customDirective.call(null, div))
    ];

    mounted = true;
}

// use: before on:
if (!mounted) {
    dispose = [
        action_destroyer(customDirective_action = customDirective.call(null, div)),
        listen(div, "success", /*success_handler*/ ctx[1])
    ];

    mounted = true;
}
person Geoff Rich    schedule 20.05.2021