Svelte v3 以编程方式创建一个带有 props 和事件监听器的组件

F L*_*has 3 svelte svelte-3

是否可以创建一个组件并以编程方式将事件侦听器附加到它?

我知道这对于<svelte:component/>通过传播使用道具很容易实现{ ...props }。我想知道是否可以实现类似的东西来附加事件侦听器。

例如,在下面的例子中,我想以编程方式连接on:messageAon:countB

<!-- App.svelte -->
<script>
    import A from './A.svelte';
    import B from './B.svelte';

    let message = 'Hi there ';
    let count = 0;

    const components = [{
        component: A,
        props: { message },
        listeners: { message: (m) => { console.log(`They say "${m}"`); } }
    }, {
        component: B,
        props: { count },
        listeners: { click: () => { count++; } }
    }];
</script>

{#each components as component}
    <div><svelte:component this={component.component} { ...component.props }/></div>
{/each}

<div>
    <p>They say "{message}"!</p>
    <p>They clicked {count} times!</p>
</div>

<!-- A.svelte -->
<script>
    import { createEventDispatcher } from 'svelte';
    const dispatch = createEventDispatcher();
    export let message = '';
    function changeHandler(e) { dispatch('message', message); }
</script>

<input on:change={changeHandler} on:value={message} value={message} />

<!-- B.svelte -->
<script>
    import { createEventDispatcher } from 'svelte';
    const dispatch = createEventDispatcher();
    export let count = 0;
    function clickHandler() { dispatch('count', count); }
</script>

<button on:click={clickHandler}>Click me</button>
Run Code Online (Sandbox Code Playgroud)

这是一个现场演示:https : //svelte.dev/repl/af1bd30ab75b43f19b72a306340b7282?version=3.18.2

即,我希望有一种方法可以将components数组扩展到

<A message={message} on:message={e => { message = e.detail; }}/>
<B count={count} on:count={e => { count = e.detail; }}/>
Run Code Online (Sandbox Code Playgroud)

Jér*_*e B 6

您可以使用$on在组件事件上动态注册侦听器。

在您的用例中,您可以使用此组件:

组件事件.svelte

<svelte:component this={component.component} { ...component.props } bind:this={instance}/>

<script>
  export let component;

    let instance;
    
    $: if (instance && component.listeners) {
        for (let [key, listener] of Object.entries(component.listeners)) {
            instance.$on(key, listener);
        }
    }
</script>
Run Code Online (Sandbox Code Playgroud)

并在您的 App.svelte 中将每个循环替换为:

{#each components as component}
    <ComponentEvent {component}/>
{/each}
Run Code Online (Sandbox Code Playgroud)

看到这个REPL