直接加载页面时turbolinks:load等事件无法触发的技术问题
解决Turbolinks动态脚本与事件触发的两个常见问题
我来帮你拆解这两个Turbolinks的典型问题,咱们一步步理清楚原因和解决办法:
问题1:首次非Turbolinks加载时,动态脚本无法触发DOMContentLoaded与turbolinks:load
原因分析
DOMContentLoaded事件在页面首次加载完成后就已经触发完毕了,如果你是动态加载脚本,等脚本加载完成时这个事件早就过去了,自然监听不到。turbolinks:load在首次页面加载时会触发,但如果你的动态脚本是在这个事件触发之后才加载完成的,同样会错过这个时机。
解决方案
写一个通用的初始化逻辑:先检查当前页面是否已经处于就绪状态,如果是就直接执行代码;同时监听turbolinks:load来应对后续的Turbolinks跳转场景。举个例子:
function initMyScript() { // 这里放你的业务代码,比如初始化组件、绑定事件等 console.log("脚本初始化完成"); } // 检查页面是否已经加载完成 if (document.readyState === "complete" || document.readyState === "interactive") { initMyScript(); } else { // 监听首次加载的DOM就绪事件 document.addEventListener("DOMContentLoaded", initMyScript); } // 监听Turbolinks跳转后的加载事件 document.addEventListener("turbolinks:load", initMyScript);
如果是用jQuery的话,可以简化成:
function initMyScript() { console.log("脚本初始化完成"); } // 兼容首次加载和Turbolinks跳转 $(document).on("turbolinks:load DOMContentLoaded", initMyScript);
问题2:直接加载页面时turbolinks:load不触发,但Turbolinks跳转时正常
原因分析
最常见的原因是Turbolinks没有正确初始化,或者你绑定turbolinks:load事件的时机太早(Turbolinks还没加载完成就绑定了)。另外,如果你是在DOMContentLoaded里绑定turbolinks:load,首次加载时也可能错过触发时机。
解决方案
- 确保Turbolinks已经启动:在页面里加入
Turbolinks.start(),通常放在Turbolinks脚本引入之后。 - 直接绑定
turbolinks:load事件,不需要包裹在其他就绪事件里。
修正后的示例代码:
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="https://rawgit.com/turbolinks/turbolinks/master/dist/turbolinks.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <title> test </title> <script> // 启动Turbolinks Turbolinks.start(); // 直接绑定turbolinks:load事件 document.addEventListener("turbolinks:load", function() { console.log("turbolinks:load 触发了"); }); // 动态加载脚本的示例 function loadScript(src) { const script = document.createElement('script'); script.src = src; script.onload = function() { // 动态脚本加载完成后,调用初始化函数 initDynamicScript(); }; document.head.appendChild(script); } function initDynamicScript() { console.log("动态脚本初始化"); // 同样监听turbolinks:load应对后续跳转 document.addEventListener("turbolinks:load", initDynamicScript); } // 首次加载时动态加载脚本 loadScript("/path/to/your/dynamic-script.js"); </script> </head> <body> <!-- 页面内容 --> <a href="/other-page" data-turbolinks="true">跳转到其他页面</a> </body> </html>
额外提示
- 尽量避免在动态脚本里重复绑定事件,可以用事件委托(比如
$(document).on('click', '.target-element', function(){...})),或者在初始化前先解绑旧事件。 - 如果你用的是Turbolinks 5+,
turbolinks:load会在首次页面加载、Turbolinks跳转、页面刷新这三种场景下触发,是替代DOMContentLoaded的统一事件。
内容的提问来源于stack exchange,提问作者Satyendra Tiwari
相关产品推荐
相关产品推荐

