前端监控四-页面和路由的监听

window事件

  1. DOMContentLoaded
    页面 DOM 加载完成就触发,无需等待依赖资源的加载。
  2. load 页面进入时上报数据
    事件在整个页面及所有依赖资源如样式表和图片都已完成加载时触发。
  3. beforeunload 页面离开时上报数据
    当浏览器窗口关闭或者刷新时,会触发 beforeunload 事件。当前页面不会直接关闭,可以点击确定按钮关闭或刷新,也可以取消关闭或刷新。
  4. unload
    当文档或一个子资源正在被卸载时,触发 unload事件。
    它在下面两个事件后被触发:
    beforeunload
    pagehide
  5. pagehide
    当用户单击浏览器的“后退”按钮时,当前页面在显示上一页之前会收到一个pagehide(页面隐藏) 事件。pagehide总是在beforeunload后触发
  6. pageshow
    当一条会话历史记录被执行的时候将会触发页面显示 (pageshow) 事件。(这包括了后退/前进按钮操作,同时也会在 onload 事件触发后初始化页面时触发)
    前进后退不会触发load事件,但会触发unload事件和pagehide 事件
  7. popstate
    history提供了popstate监听事件,但是只有以下两种情况会触发该事件
    • 点击浏览器前进后退的按钮
    • 显示调用history的back、go、forward方法
      不能触发事件的方式
    • pushState和replaceState
    • a标签不能触发,因为非锚点模式直接跳转了页面。

路由的变化本质上都会调用history.pushState或replaceState.
当直接调用history接口时,不会触发,需要重写pushState,replaceState的原型方法

window.onpopstate = function(event) {
  alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};

history.pushState({page: 1}, "title 1", "?page=1");
history.pushState({page: 2}, "title 2", "?page=2");
history.replaceState({page: 3}, "title 3", "?page=3");
history.back(); // 弹出 "location: http://example.com/example.html?page=1, state: {"page":1}"
history.back(); // 弹出 "location: http://example.com/example.html, state: null
history.go(2);  // 弹出 "location: http://example.com/example.html?page=3, state: {"page":3}
  1. hashchange
    单页面hash路由的监听
    • 浏览器前进后退改变URL
    • 通过a标签锚点方式改变URL。
    • 通过window.location.hash改变URL
    • 调用history的back、go、forward方法
      不能触发事件的方式
    • pushState和replaceState

document事件

  1. visibilitychange
document.addEventListener("visibilitychange", function() {
  console.log( document.visibilityState );
  // Modify behavior...
});

当其选项卡的内容变得可见或被隐藏时,会在文档上触发 visibilitychange (能见度更改) 事件。

  • ‘visible’ : 此时页面内容至少是部分可见。即此页面在前景标签页中,并且窗口没有最小化。
  • ‘hidden’ : 此时页面对用户不可见。即文档处于背景标签页或者窗口处于最小化状态,或者操作系统正处于 ‘锁屏状态’ .
  • ‘prerender’ : 页面此时正在渲染中,因此是不可见的 (considered hidden for purposes of document.hidden). 文档只能从此状态开始,永远不能从其他值变为此状态。注意:浏览器支持是可选的。

在会话结束时发送统计数据

网站通常希望在用户完成页面浏览后向服务器发送分析或诊断数据,最可靠的方法是在 visibilitychange 事件发生时发送数据:

document.addEventListener('visibilitychange', function logData() {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/log', analyticsData);
  }
});

避免使用 unload 和 beforeunload

过去,许多网站使用 unload 或 beforeunload 事件以在会话结束时发送统计数据。然而这是不可靠的,在许多情况下(尤其是移动设备)浏览器不会产生 unload、beforeunload 或 pagehide 事件。下面列出了一种不触发上述事件的情况:

  1. 用户加载了网页并与其交互。
  2. 完成浏览后,用户切换到了其他应用程序,而不是关闭选项卡。
  3. 随后,用户通过手机的应用管理器关闭了浏览器应用。
  • 此外,unload 事件与现代浏览器实现的往返缓存(bfcache)不兼容。

  • 在部分浏览器(如:Firefox)通过在 bfcache 中排除包含 unload 事件处理器的页面来解决不兼容问题,

  • 但这存在性能损失。其他浏览器,例如 Safari 和 Android 上的 Chrome 浏览器则采取用户在同一标签页下导航至其他页面时不触发 unload 事件的方法来解决不兼容问题。

  • Firefox 也会在 bfcache 中排除包含 beforeunload 事件处理器的页面。

  • 解释:bfcache
    现代浏览器在根据历史记录进行前进/后退操作时,会启用缓存机制,名为“bfcache”(back-forward cache,往返缓存),它使页面导航非常快。直到用户关闭浏览器,这个缓存状态才会被删除。

使用 pagehide 作为回退

可使用 pagehide 事件来代替部分浏览器未实现的 visibilitychange 事件。和 beforeunload 与 unload 事件类似,这一事件不会被可靠地触发(特别是在移动设备上),但它与 bfcache 兼容。

https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/sendBeacon
https://www.cnblogs.com/SyMind/p/8485332.html

实践

监听页面进入离开

  • 如何监听页面的进入和离开?
  • 对于常规页面的 首次加载、页面关闭、刷新 等操作都可以通过 window.onload 和 window.onbeforeunload 事件来监听
  • 页面进入和离开,浏览器前进后退可以通过 pageshow 和 pagehide 处理。

单页面应用路由监听

目前主流的单页应用大部分都是基于 browserHistory (history api) 或者 hashHistory 来做路由处理,我们可以通过监听路由变化来判断页面是否有可能切换。注意是有可能切换,因为单纯的描点触发不是一个新的url

hashchange和popstate事件的特性区别

https://developer.mozilla.org/zh-CN/docs/Web/API/History_API

  • hashchange是老API, 浏览器支持度高, 本来是用来监听hash变化的, 可以被利用来做客户端前进后退, 但应该不是这个API的存在的主要目的.

  • 而popstate, 及相关api, pushState等属于HTML5新标准, 产生的目的就是做客户端前进后退的, 不仅可以支持hash, 非hash的同源url也支持.所以一般用法是浏览器支持就用popstate, 不支持再降级使用hashchange

  • 描点的触发不会发出popstate事件,但会发出hashchange事件

  • pushState和replaceState均不能触发hashchang,popstate事件

  • 所以无论是hash还是history模式,使用popstate事件既可以监听到hash的变化(描点不会触发),也能监听到浏览器的前进后退

  • 通过 popstate 事件能解决一半问题,因为 popstate 只会在浏览器前进后退的时候触发,当调用 history.pushState() or history.replaceState() 的时候并不会触发。需要重写window.history.pushState和window.history.replaceState这两个API,在重写的方法里面触发路由的收集。

  • 注意:当hashchange发生时,IE不会触发popstate,IE浏览器中我们需要做降级处理

 var e = null
 "on" + (e = window.ActiveXObject || "ActiveXObject" in window ? "hashchange" : "popstate") in window && window.addEventListener(e, function(){console.log(location.href)})

一般情况我们很少考虑ie。

Demo

const pageTracking = () => {
       const sendToAnalytics = () => {
           const data = {
               url: location.href,
               title: document.title,
               referrer: document.referrer
           }
           fetch('https://example.com', {
               method: 'POST',
               headers: {
                   'Content-Type': 'application/json',
               },
               body: JSON.stringify(data),
           })
       }
       const pushState = window.history.pushState
       const replaceState = window.history.replaceState;
       window.history.pushState = function () {
           pushState.apply(window.history, arguments)
           sendToAnalytics.apply()
       }
       window.history.replaceState = function () {
           replaceState.apply(window.history, arguments)
           sendToAnalytics.apply()
       };
       window.addEventListener('popstate', function (event) {
           sendToAnalytics.apply()
       });
       window.addEventListener('load', function (event) {
           sendToAnalytics.apply()
       })
       window.addEventListener('beforeunload', function (event) {
           sendToAnalytics.apply()
       });
   }

vue路由中的全局钩子

vue项目使用路由钩子是最方便的

  • 全局后置钩子
    你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
  sendToAnalytics(to.fullPath)
})

它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值