Vitest测试Svelte组件遇‘Function called outside component initialization’错误
问题解决:Svelte组件测试时
Function called outside component initialization错误 问题现象
使用Vitest测试倒计时Svelte组件时,执行import Countdown from "../lib/Countdown.svelte"导入操作就触发错误:Function called outside component initialization,报错指向onDestroy调用。
错误原因
- 生命周期函数调用时机错误:组件中使用了
<script context="module">模块级脚本,该脚本在组件被导入时就会执行,而onDestroy是组件实例的生命周期函数,只能在组件实例初始化阶段调用,模块脚本执行时还未创建组件实例,因此触发错误。 - 变量作用域问题:模块级脚本中的变量(如
time、running)是所有组件实例共享的,多个实例会互相干扰倒计时逻辑,不符合组件独立性要求。
修复步骤
- 移除脚本的
context="module"属性,将模块级脚本改为普通组件脚本,确保变量和生命周期函数属于单个组件实例。 - 导入
onMount生命周期函数,将startCountdown()的调用放在onMount中,确保组件初始化完成后再启动倒计时。 - 保留
onDestroy逻辑,用于组件销毁时停止倒计时。
修改后的组件代码
<script> import {push} from 'svelte-spa-router' import {onDestroy, onMount} from 'svelte' let time = 1000*120; let interval = 1000; let running = true; const twoDigits = (number) => { return number.toLocaleString('en-US', { minimumIntegerDigits: 2, useGrouping: false }) } const timeString = (ms) => { let seconds = ms / 1000; const minutes = Math.floor(seconds / 60); seconds = seconds % 60; const timeString = twoDigits(minutes) + ":" + twoDigits(seconds); return timeString } let timeShown = timeString(time) const startCountdown = () => { setTimeout(()=>{ time -= interval; timeShown = timeString(time); if (time > 0 && running) { startCountdown(); } else if (time > 0 && !running) { console.log("Countdown stopped") } else { console.log("Done!") setTimeout( () => { push('/gameover') },1000) } }, interval) } onMount(() => { startCountdown() }) onDestroy(()=>{ running = false; }) </script> <div id="countdown"> {timeShown} </div>
测试文件与配置说明
- 测试文件无需修改,导入组件后可正常执行测试。
vite.config.js配置保持不变即可。
内容的提问来源于stack exchange,提问作者Jan Seipel
相关产品推荐
相关产品推荐

