SvelteKit中<svelte:head>内JS文件仅首次加载,刷新后失效
解决SvelteKit中Static目录JS文件仅首次加载生效的问题
原因分析
- SvelteKit采用客户端路由导航时,页面不会完全刷新,
DOMContentLoaded事件仅在首次页面加载时触发一次,后续路由切换、页面刷新都不会重新触发该事件。 - 浏览器会缓存已加载的JS文件,重复添加相同
src的<script>标签时,不会重新执行脚本,也不会触发on:load事件。
具体解决方案
方案1:抽离脚本逻辑为可调用函数,在组件生命周期触发
修改/static/js/script.js,将DOMContentLoaded内的逻辑抽成独立函数:
// /static/js/script.js window.initScript = function() { // 原DOMContentLoaded中的业务逻辑写在这里 console.log('脚本初始化完成'); }; // 保留首次加载的触发逻辑,兼容直接访问页面的场景 document.addEventListener("DOMContentLoaded", window.initScript);
在布局组件中利用onMount钩子,每次组件挂载时调用该函数:
<script> import { onMount } from 'svelte'; onMount(() => { // 确保脚本已加载后调用初始化函数 if (window.initScript) { window.initScript(); } }); </script> <svelte:head> <link rel="stylesheet" href="/css/style.css" /> <script src="/js/script.js"></script> </svelte:head> <slot />
方案2:通过app.html注入脚本,监听路由变化重新执行
在src/app.html的<body>末尾添加脚本,监听SvelteKit的路由结束事件:
<!-- src/app.html --> <body> %sveltekit.body% <script src="/js/script.js"></script> <script> // 每次路由切换完成后重新执行脚本逻辑 window.addEventListener('sveltekit:navigation-end', () => { if (window.initScript) { window.initScript(); } }); </script> </body>
对应的script.js需将初始化逻辑挂载到window对象上(同方案1中的脚本修改方式)。
方案3:强制特定路由完全刷新(仅适用于特殊场景)
如果某个页面必须完全刷新才能正常工作,可在路由组件中添加配置:
<script> // 强制该路由使用服务端渲染且禁用客户端导航 export const ssr = true; export const csr = false; </script> <!-- 页面内容 -->
关于on:load事件不触发的说明
浏览器加载过的JS文件会被缓存,重复添加相同src的<script>标签时,不会重新发起请求,自然也不会触发on:load事件。若需验证脚本加载状态,可直接在脚本内部添加console.log输出,或通过DOM查询确认脚本标签是否存在。
内容的提问来源于stack exchange,提问作者user3291025
相关产品推荐
相关产品推荐

