Svelte v3 以编程方式创建具有道具和事件侦听器的组件
Svelte v3 programmatically create a component with props and event listeners
是否可以创建组件并以编程方式将事件侦听器附加到它?
我知道这对于使用 <svelte:component/>
的道具来说很容易通过 { ...props }
传播。我想知道是否可以实现类似的东西来附加事件侦听器。
例如,在下面的示例中,我想以编程方式将 on:message
附加到 A
并将 on:count
附加到 B
:
<!-- 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>
这是一个现场演示: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; }}/>
不确定您是否可以像您正在寻找的那样以编程方式附加它们,但您可以在对象中传递函数或回调,并说明 svelte:component 标记中的每个潜在调度事件,如下所示:
<svelte:component
this={component.component}
{ ...component.props }
on:message={ component.function}
on:count={ component.function}
/>
这是 REPL 中的一个工作示例,它显示了对象中的箭头函数和回调(如果需要更丰富的函数)回调仍然获取事件详细信息。
如果组件中不存在分派的事件,我认为不会发生任何事情,但如果您需要一个组件来分派多个事件,您将需要其他东西。
你不能动态附加监听器,不 - 不要忘记 Svelte 是一种编译语言,它在编译时完成所有繁重的工作,所以需要提前知道事情。
我对动态监听器所做的是触发单个已知事件,然后让事件细节包含差异逻辑,例如事件名称等。如下所示:
// SomeComponent.svelte
<script>
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
dispatch('component-event', { name: 'alert', value: 'oh noes' })
dispatch('component-event', { name: 'log', value: 'some message' })
</script>
// App.svelte
<svelte:component this={someComponent} on:component-event={e => handleEvent(e)} />
<script>
function handleEvent ({ detail }) {
const { name, value } = detail
if (name === 'alert') { alert(value) }
if (name === 'log') { console.log(value) }
}
</script>
您可以使用$on
在组件事件上动态注册侦听器。
在您的用例中,您可以使用此组件:
ComponentEvent.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>
并用 App.svelte 替换每个循环:
{#each components as component}
<ComponentEvent {component}/>
{/each}
看到这个REPL
是否可以创建组件并以编程方式将事件侦听器附加到它?
我知道这对于使用 <svelte:component/>
的道具来说很容易通过 { ...props }
传播。我想知道是否可以实现类似的东西来附加事件侦听器。
例如,在下面的示例中,我想以编程方式将 on:message
附加到 A
并将 on:count
附加到 B
:
<!-- 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>
这是一个现场演示: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; }}/>
不确定您是否可以像您正在寻找的那样以编程方式附加它们,但您可以在对象中传递函数或回调,并说明 svelte:component 标记中的每个潜在调度事件,如下所示:
<svelte:component
this={component.component}
{ ...component.props }
on:message={ component.function}
on:count={ component.function}
/>
这是 REPL 中的一个工作示例,它显示了对象中的箭头函数和回调(如果需要更丰富的函数)回调仍然获取事件详细信息。
如果组件中不存在分派的事件,我认为不会发生任何事情,但如果您需要一个组件来分派多个事件,您将需要其他东西。
你不能动态附加监听器,不 - 不要忘记 Svelte 是一种编译语言,它在编译时完成所有繁重的工作,所以需要提前知道事情。
我对动态监听器所做的是触发单个已知事件,然后让事件细节包含差异逻辑,例如事件名称等。如下所示:
// SomeComponent.svelte
<script>
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
dispatch('component-event', { name: 'alert', value: 'oh noes' })
dispatch('component-event', { name: 'log', value: 'some message' })
</script>
// App.svelte
<svelte:component this={someComponent} on:component-event={e => handleEvent(e)} />
<script>
function handleEvent ({ detail }) {
const { name, value } = detail
if (name === 'alert') { alert(value) }
if (name === 'log') { console.log(value) }
}
</script>
您可以使用$on
在组件事件上动态注册侦听器。
在您的用例中,您可以使用此组件:
ComponentEvent.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>
并用 App.svelte 替换每个循环:
{#each components as component}
<ComponentEvent {component}/>
{/each}
看到这个REPL