javascript基础学习系列二百七十八:beforeunload 事件

beforeunload 事件会在 window 上触发,用意是给开发者提供阻止页面被卸载的机会。这个事件
会在页面即将从浏览器中卸载时触发,如果页面需要继续使用,则可以不被卸载。这个事件不能取消, 否则就意味着可以把用户永久阻拦在一个页面上。相反,这个事件会向用户显示一个确认框,其中的消 息表明浏览器即将卸载页面,并请用户确认是希望关闭页面,还是继续留在页面上

为了显示类似图 17-8 的确认框,需要将 event.returnValue 设置为要在确认框中显示的字符串 (对于 IE 和 Firefox 来说),并将其作为函数值返回(对于 Safari 和 Chrome 来说),如下所示:

window.addEventListener("beforeunload", (event) => {
  let message = "I'm really going to miss you if you go.";
  event.returnValue = message;
  return message;
});

3. DOMContentLoaded 事件

window 的 load 事件会在页面完全加载后触发,因为要等待很多外部资源加载完成,所以会花费 较长时间。而 DOMContentLoaded 事件会在 DOM 树构建完成后立即触发,而不用等待图片、JavaScript
文件、CSS 文件或其他资源加载完成。相对于 load 事件,DOMContentLoaded 可以让开发者在外部资 18 源下载的同时就能指定事件处理程序,从而让用户能够更快地与页面交互。

要处理 DOMContentLoaded 事件,需要给 document 或 window 添加事件处理程序(实际的事件 目标是 document,但会冒泡到 window)。下面是一个在 document 上监听 DOMContentLoaded 事件 的例子:

19 console.log("Content loaded"); 20
 document.addEventListener("DOMContentLoaded", (event) => { });
DOMContentLoaded 事件的 event 对象中不包含任何额外信息(除了 target 等于 document)。
DOMContentLoaded 事件通常用于添加事件处理程序或执行其他 DOM 操作。这个事件始终在 load 21 事件之前触发。
对于不支持 DOMContentLoaded 事件的浏览器,可以使用超时为 0setTimeout()函数,通过 其回调来设置事件处理程序,比如: 22
 setTimeout(() => {
// 在这里添加事件处理程序
}, 0);

以上代码本质上意味着在当前 JavaScript 进程执行完毕后立即执行这个回调。页面加载和构建期间, 只有一个 JavaScript 进程运行。所以可以在这个进程空闲后立即执行回调,至于是否与同一个浏览器或 同一页面上不同脚本的 DOMContentLoaded 触发时机一致并无绝对把握。为了尽可能早一些执行,以 上代码最好是页面上的第一个超时代码。即使如此,考虑到各种影响因素,也不一定保证能在 load 事 件之前执行超时回调。

readystatechange 事件

IE 首先在 DOM 文档的一些地方定义了一个名为 readystatechange 事件。这个有点神秘的事件 旨在提供文档或元素加载状态的信息,但行为有时候并不稳定。支持 readystatechange 事件的每个 对象都有一个 readyState 属性,该属性具有一个以下列出的可能的字符串值。
 uninitialized:对象存在并尚未初始化。
 loading:对象正在加载数据。
 loaded:对象已经加载完数据。
 interactive:对象可以交互,但尚未加载完成。  complete:对象加载完成。

看起来很简单,其实并非所有对象都会经历所有 readystate 阶段。文档中说有些对象会完全跳过 某个阶段,但并未说明哪些阶段适用于哪些对象。这意味着 readystatechange 事件经常会触发不到 4 次,而 readyState 未必会依次呈现上述值。
在 document 上使用时,值为"interactive"的 readyState 首先会触发 readystatechange 事件,时机类似于 DOMContentLoaded。进入交互阶段,意味着 DOM 树已加载完成,因而可以安全地 交互了。此时图片和其他外部资源不一定都加载完了。可以像下面这样使用 readystatechange 事件:

document.addEventListener("readystatechange", (event) => { if (document.readyState == "interactive") {
        console.log("Content loaded");
      }
});

这个事件的 event 对象中没有任何额外的信息,连事件目标都不会设置。
在与 load 事件共同使用时,这个事件的触发顺序不能保证。在包含特别多或较大外部资源的页面 中,交互阶段会在 load 事件触发前先触发。而在包含较少且较小外部资源的页面中,这个 readystatechange 事件有可能在 load 事件触发后才触发。
让问题变得更加复杂的是,交互阶段与完成阶段的顺序也不是固定的。在外部资源较多的页面中, 很可能交互阶段会早于完成阶段,而在外部资源较少的页面中,很可能完成阶段会早于交互阶段。因此, 实践中为了抢到较早的时机,需要同时检测交互阶段和完成阶段。比如:

document.addEventListener("readystatechange", (event) => { if (document.readyState == "interactive" ||
document.readyState == "complete") { document.removeEventListener("readystatechange", arguments.callee); console.log("Content loaded");
} });

当 readystatechange 事件触发时,这段代码会检测 document.readyState 属性,以确定当前 是不是交互或完成状态。如果是,则移除事件处理程序,以保证其他阶段不再执行。注意,因为这里的 事件处理程序是匿名函数,所以使用了 arguments.callee 作为函数指针。然后,又打印出一条表示 内容已加载的消息。这样的逻辑可以保证尽可能接近使用 DOMContentLoaded 事件的效果。

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用`window.addEventListener('beforeunload',)`时,偶尔不生效可能是由于以下几种原因: 1. 网页未能完全加载完成的时候,`beforeunload`事件可能无法正确触发。这可能是因为网页中包含了大量的资源或者网络连接不稳定导致页面加载时间过长,从而导致事件无法响应。 2. 常见的浏览器拓展或插件也可能干扰`beforeunload`事件的正常触发。这些插件或拓展可能修改了浏览器的默认行为,从而导致事件无法被正确执行。 3. 一些浏览器在关闭时可能会默认阻止`beforeunload`事件的弹出框。这种情况下,用户关闭页面时无法触发事件的响应。 为了解决这个问题,可以尝试以下方法: 1. 使用`DOMContentLoaded`事件代替`beforeunload`事件。`DOMContentLoaded`事件在网页加载完成后立即触发,可以用来执行与页面卸载前类似的操作。 2. 检查网页的加载速度和性能,确保网页能够及时加载完成,从而避免`beforeunload`事件无法触发的情况。 3. 检查已安装的浏览器插件或拓展,可能需要禁用一些可能干扰事件触发的插件。 4. 在弹出的`beforeunload`事件中,提示用户保存未提交的更改或提醒用户将要离开网页,以增加用户的留存时间。 综上所述,`window.addEventListener('beforeunload',)`在关闭页面时偶尔不生效可能是由于页面加载速度、浏览器插件或拓展以及浏览器默认行为等原因造成的。通过优化网页加载速度、检查和禁用干扰事件的插件,以及增加用户留存时间的提示,可能有助于解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值