0

我正在寻找一种方法来侦听来自 JavaScript(而不是on:语法)的另一个组件中的 Svelte 组件的调度事件。

是我试图在 REPL 上实现的代码。

预期的行为是在单击按钮关闭 0在控制台中显示0 ,其他的以此类推。

4

2 回答 2

2

我在 svelte 的编译代码中进行了一些挖掘,我找到了一个解决方案来监听 svelte 处理的事件,但它并不漂亮:)

您可以(并且应该)在调用时调度自己的自定义事件onClose,但解决方案如下:

在 Nested.svelte 上

<script context="module">
    let counter = 0
</script>

<script>
    import { createEventDispatcher, onMount } from 'svelte';
    // add this
    import { get_current_component } from 'svelte/internal'; 
    let _this;
    const id = counter++
  const dispatch = createEventDispatcher()
    /*********
     and add this reactive statement
    **********/
    $: {
        if (_this){
            _this.parentNode.hosts = (_this.parentNode.hosts || []);
            _this.parentNode.hosts.push(get_current_component());
        }
    } 
    /*********
     end
    **********/
    function onClose() {
        dispatch('close', id)
    }
</script>
<!-- bind this -->
<button bind:this={_this} class='nested-button' on:click={onClose}>
    Close {id}
</button>

然后在你的 App.svelte

<script>
    import { onMount } from 'svelte'
    import Nested from './Nested.svelte'

    let element

    onMount(() => {
        // requestAnimationFrame is required!
        requestAnimationFrame(() => element.hosts.forEach(nestedButton => {
        nestedButton.$on('close', (e) => {
                console.log(e.detail)
            })
        }));
    })
</script>

<ul bind:this={element}>
    <Nested/>
    <Nested  />
    <Nested />
</ul>

解释 -

绑定到 svelte 事件的唯一方法是获取对调用组件的引用并调用该$on方法,但目前没有简单的方法来获取组件的引用。

所以我所做的是调用 svelte 的 internal get_current_component,它将返回当前组件(但由于某种原因在 inside 调用时不起作用onMount)。

我附加了对parentNode.hosts组件中最顶层元素的引用,在本例中是ul元素。

然后你可以$on为每个引用调用方法element.hosts

然而,适当的解决方案将像这样调度您自己的事件:

function onClose() {
        dispatch('close', id)
        this.dispatchEvent(new CustomEvent('close', {detail: id}));
    }

并且通过实现几乎完全相同的事情而不会弄乱svelte的内部结构

于 2020-04-27T19:33:20.943 回答
1

我利用苗条的商店和反应性:

信号.js:

import { writable } from 'svelte/store';
export const endSignal = writable({});

发件人.svelte:

<script>
import { endSignal } from './signals.js';
const signal = $endSignal;

function handleEndSignal(){
  // do other stuff, then send signal
  endSignal.update(()=> signal);
}
</script>

<button on:click={handleEndSignal}>The End</button>

Receiver.svelte:

<script>
import { endSignal } from './signals.js';

$: endItAll(), $endSignal;

let countEnds = 0;

function endItAll(){
  countEnds +=1;
}
</script>

<p>times end signal received: {countEnds}</p>

基本上,每次我们单击 Sender.svelte 中的按钮时,“signals.js”中的值“endSignal”都会被覆盖,因此在 Receiver.svelte 中,“$:”语句中的更新变量会触发函数“endItAll()” .

于 2021-08-04T15:51:35.693 回答