为何旧版Svelte的dispatch语法可运行,更新后失效?
一、旧版Svelte中dispatch('myEvent')的运行逻辑
在你使用的Svelte ^3.46.2版本中,createEventDispatcher()返回的dispatch函数有特殊设计:当调用dispatch('myEvent')时,它不会立即派发事件,而是返回一个预绑定了事件名myEvent的回调函数。这个函数会在点击事件触发时被浏览器调用,进而完成事件派发。
所以当时直接写on:click={dispatch('myEvent')}是有效的——本质是把dispatch返回的回调函数赋值给点击事件监听,完全符合addEventListener对第二个参数(函数类型)的要求。
二、更新后语法失效的原因
后续Svelte版本对dispatch的API行为做了调整:调用dispatch('myEvent')会立即执行事件派发,不再返回函数。此时把dispatch('myEvent')赋值给on:click会触发两个问题:
- 组件初始化阶段就会自动执行一次
dispatch('myEvent'),违背点击触发的预期; dispatch执行后的返回值(通常是undefined)被传给addEventListener的第二个参数,而该参数要求必须是函数对象,因此触发报错:
Failed to execute 'addEventListener' on 'EventTarget': parameter 2 is not of type 'Object'.
正确写法on:click={() => dispatch('myEvent')}用箭头函数包裹dispatch调用,只有点击事件触发时才会执行内部的dispatch,既满足事件监听对回调函数的要求,又实现了点击派发事件的逻辑。
三、关键更新包定位
核心变更来自svelte包本身。你的旧配置中svelte版本是^3.46.2,更新时大概率将其升级到了3.x后续的某个版本(该API调整属于Svelte 3的内部行为优化,无大版本号变更)。
若同步升级了rollup-plugin-svelte,它只是适配新版本Svelte的编译逻辑,语法失效的根源仍是Svelte核心库中createEventDispatcher的行为变更。
内容的提问来源于stack exchange,提问作者Przemek

