Svelte中如何捕获动态组件抛出的事件?
解决Svelte动态组件事件无法捕获的问题
要捕获动态组件抛出的事件,核心是处理Svelte事件命名的自动转换规则——静态组件的事件监听会自动将驼峰式(camelCase)转换为kebab-case,但<svelte:component>不会做这个转换,导致事件名匹配失败。下面是两种可行的解决方案:
方案一:统一使用kebab-case事件名(推荐)
Svelte的createEventDispatcher会自动把驼峰事件名转为kebab-case派发,静态组件的on:xxx监听也会同步转换,但动态组件不会。因此只需把动态组件的监听改为kebab-case格式即可:
修改后的ComponentA
<script> import { type ComponentType} from "svelte"; import { ConcreteComponent } from "./ConcreteComponent.svelte" export let components:ComponentType[]; export let component: ComponentType; function handleMessage(event: CustomEvent<{text:string}>) { console.log(event.detail.text); } </script> <!-- 静态组件的驼峰监听依然有效,Svelte会自动转换 --> <ConcreteComponent on:customTestEvent={handleMessage}/> <!-- 动态组件改用kebab-case事件名监听 --> <svelte:component this={component} on:custom-test-event={handleMessage}/>
如果希望代码风格更统一,也可以直接在组件中用kebab-case派发事件:
DynamicComponent.svelte
<script> import { createEventDispatcher } from 'svelte'; // 泛型定义改为kebab-case事件名 const dispatch = createEventDispatcher<{ "custom-test-event": {text:string}}>(); function raiseEvent() { dispatch("custom-test-event", {text: "Dynamic!"}); } </script>
ConcreteComponent.svelte
<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher<{ "custom-test-event": {text:string}}>(); function raiseEvent() { dispatch("custom-test-event", {text: "Concrete!"}); } </script>
此时ComponentA的监听可以统一用on:custom-test-event,静态和动态组件都能正常触发。
方案二:手动派发原始驼峰事件名(不推荐)
如果必须保留驼峰事件名,可以绕过createEventDispatcher,手动创建CustomEvent并派发(需要开启冒泡让父组件捕获):
修改后的DynamicComponent.svelte
<script> function raiseEvent() { const event = new CustomEvent("customTestEvent", { detail: { text: "Dynamic!" }, bubbles: true, composed: true // 组件含Shadow DOM时需要添加 }); dispatchEvent(event); } </script>
这时ComponentA中原来的on:customTestEvent={handleMessage}就能正常监听动态组件的事件了。
内容的提问来源于stack exchange,提问作者Harms Oxmas
相关产品推荐
相关产品推荐

