IE11因非SSL内容致readyState异常、DOM事件失效的解决方案问询
这个问题在IE11里确实挺棘手的——混合内容提示会把页面加载流程彻底卡住,直到用户手动选择,哪怕你根本不需要那些不安全的资源。不过有几个可行的方案可以规避,我来一步步说:
1. 提前阻止混合内容触发提示
最根本的办法是不让浏览器弹出那个提示,这样页面加载流程就不会被中断。你可以通过以下两种方式实现:
用Content-Security-Policy阻止不安全资源
给页面添加CSP元标签,直接阻止所有混合内容加载,IE11对这个属性的基础支持是有的:
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
这个标签会告诉浏览器自动拒绝所有非HTTPS的资源请求,不会弹出提示,页面就能正常走完加载流程,DOMContentLoaded也能正常触发。
手动移除/清空不安全资源
如果CSP的方式不生效(毕竟IE11的CSP支持不算完美),可以在页面加载的最早期(比如<head>的最顶部)插入一段脚本,遍历并移除所有带http://前缀的外部资源:
// 放在<head>最前面,确保在浏览器请求资源前执行 (function() { // 查找所有不安全的脚本、图片、样式 var insecureElements = document.querySelectorAll( 'script[src^="http://"], img[src^="http://"], link[href^="http://"]' ); for (var i = 0; i < insecureElements.length; i++) { var el = insecureElements[i]; // 直接移除脚本,清空图片/样式的资源地址 if (el.tagName === 'SCRIPT') { el.parentNode.removeChild(el); } else { el.src = el.href = 'data:'; // 用空白data URI代替 } } })();
这样浏览器就不会去请求那些不安全的资源,自然也就不会弹出提示,页面加载不会被阻塞。
2. 绕过DOMContentLoaded,用readyState监听
如果上面的方法还是没解决,或者你需要兼容更极端的情况,可以直接监听document.readyState的变化,这在IE11里不会被混合内容提示阻塞:
document.onreadystatechange = function() { // 当DOM解析完成,readyState会变为interactive,此时可以执行初始化代码 if (document.readyState === 'interactive') { // 这里放你原本要在DOMContentLoaded里执行的逻辑 initYourApplication(); } };
这个事件会在DOM结构准备好时触发,不管浏览器有没有弹出混合内容提示,都能正常执行你的安全JS代码。
3. 手动触发DOMContentLoaded事件
如果确认DOM已经准备完毕,但事件还是没触发,可以手动创建并触发事件:
// 检查当前readyState,如果已经处于可交互状态,手动触发事件 if (document.readyState === 'interactive' || document.readyState === 'complete') { var domLoadedEvent = document.createEvent('Event'); domLoadedEvent.initEvent('DOMContentLoaded', true, true); document.dispatchEvent(domLoadedEvent); }
这个方法适合那些依赖DOMContentLoaded事件绑定的现有代码,不用修改太多逻辑。
总结
优先尝试block-all-mixed-content的CSP方案,最省心;如果不行就手动移除不安全资源;最后用readyState监听或者手动触发事件兜底。这些方法都能让你的安全JS正常执行,不用等用户处理那个烦人的提示。
内容的提问来源于stack exchange,提问作者user2693017

