告别弃用API!手把手教你用performance.getEntriesByType检测页面刷新与跳转

告别弃用API!手把手教你用performance.getEntriesByType检测页面刷新与跳转

最近在重构一个老项目时,我遇到了一个棘手的问题:原本用来判断页面是刷新还是首次加载的performance.navigation.type在Chrome控制台里赫然标着"Deprecated"(已弃用)。这让我意识到,很多前端开发者可能还在使用这个即将被淘汰的API,而新的替代方案PerformanceNavigationTiming虽然功能更强大,但相关资料却比较零散。

如果你也在为如何准确判断用户是通过刷新、前进后退还是正常导航进入页面而烦恼,这篇文章就是为你准备的。我会带你从零开始,深入理解这个API的演变历程,并给出实际可用的代码方案。

1. 为什么我们需要关注页面导航类型?

在开始技术细节之前,先聊聊为什么这个看似简单的功能如此重要。在我负责的一个电商项目中,我们需要根据用户进入页面的方式采取不同的策略:

  • 首次加载:需要完整加载所有资源,初始化应用状态
  • 页面刷新:可能需要重新获取某些动态数据,但可以复用部分缓存
  • 前进/后退:可以利用浏览器缓存,甚至恢复之前的滚动位置和表单状态

以前我们依赖performance.navigation.type来做这些判断,但随着浏览器标准的演进,这个API已经被标记为弃用。更糟糕的是,不同浏览器的实现细节存在差异,导致我们的判断逻辑在某些边缘情况下失效。

1.1 传统方法的局限性

让我先展示一下我们之前使用的代码,这也是很多项目中常见的写法:

// 已弃用的传统写法
function detectNavigationTypeOld() {
  const nav = window.performance.navigation;
  
  switch(nav.type) {
    case 0: // TYPE_NAVIGATE
      console.log('正常导航(点击链接、输入URL等)');
      return 'navigate';
    case 1: // TYPE_RELOAD
      console.log('页面刷新');
      return 'reload';
    case 2: // TYPE_BACK_FORWARD
      console.log('前进/后退');
      return 'back_forward';
    default:
      console.log('未知导航类型');
      return 'unknown';
  }
}

这段代码的问题在于:

  1. API已弃用:现代浏览器中会收到警告
  2. 类型值硬编码:0、1、2这些魔法数字让代码难以维护
  3. 信息有限:只能获取基本导航类型,缺少详细的性能数据

1.2 新API的优势

相比之下,新的PerformanceNavigationTiming API提供了更丰富的信息:

特性 旧API (performance.navigation) 新API (PerformanceNavigationTiming)
导航类型 仅type属性 详细的type字符串值
时间信息 完整的导航时间线数据
重定向信息 redirectCount 详细的redirectStart/End时间
资源大小 encodedBodySize, decodedBodySize等
协议信息 nextHopProtocol
兼容性 已弃用 现代浏览器广泛支持

2. 深入理解PerformanceNavigationTiming

2.1 获取导航信息的新方法

让我们先看看如何获取新的导航信息。与直接访问performance.navigation不同,新API需要通过getEntriesByType方法:

// 获取导航性能条目的推荐方法
function getNavigationTiming() {
  // 方法1:使用getEntriesByType
  const navEntries = performance.getEntriesByType('navigation');
  
  if (navEntries.length > 0) {
    const navTiming = navEntries[0];
    console.log('导航类型:', navTiming.type);
    console.log('完整导航对象:', navTiming);
    return navTiming;
  }
  
  // 方法2:使用PerformanceObserver(更推荐)
  return null;
}

这里有个重要的细节:getEntriesByType('navigation')返回的是一个数组,即使通常只有一个导航条目。这是因为理论上一个页面可能有多个导航(比如iframe),但实践中我们通常取第一个。

2.2 导航类型的详细解读

新的type属性返回的是字符串,而不是数字,这让代码更加清晰:

// 新的导航类型判断
function detectNavigationType() {
  const navEntries = performance.getEntriesByType('navigation');
  
  if (navEntries.length === 0) {
    console.warn('未找到导航性能条目');
    return 'unknown';
  }
  
  const navTiming = navEntries[0];
  
  switch(navTiming.type) {
    case 'navigate':
      console.log('正常导航:用户通过点击链接、输入URL、提交表单等方式进入');
      break;
    case 'reload':
      console.log('页面刷新:通过刷新按钮、F5、location.reload()等方式');
      break;
    case 'back_forward':
      console.log('前进/后退:通过浏览器历史记录导航');
      break;
    case 'prerender':
      console.log('预渲染:页面在后台预加载');
      break;
    default:
      console.log('未知导航类型:', navTiming.type);
  }
  
  return navTiming.type;
}

注意prerender类型在某些浏览器中可能不会出现,或者需要特定的配置才能触发。在实际使用中,我们主要关注前三种类型。

2.3 完整的导航时间线

PerformanceNavigationTiming最强大的功能之一是提供了完整的导航时间线。我们可以通过这些时间点计算各种性能指标:

// 计算关键性能指标
function calculatePerformanceMetrics() {
  const navEntries = performance.getEntriesByType('navigation');
  
  if (navEntries.length === 0) return null;
  
  const timing = navEntries[0];
  
  const metrics = {
    // 导航类型
    navigationType: timing.type,
    
    // DNS查询时间
    dnsLookupTime: timing.domainLookupEnd - timing.domainLookupStart,
    
    // TCP连接时间
    tcpConnectTime: timing.connectEnd - timing.connectStart,
    
    // SSL握手时间(仅HTTPS)
    sslHandshakeTime: timing.secureConnectionStart > 0 
      ? timing.connectEnd - timing.secureConnectionStart 
      : 0,
    
    // 请求响应时间(TTFB)
    timeToFirstByte: timing.responseStart - timing.requestStart,
    
    // 内容下载时间
    contentDownloadTime: timing.responseEnd - timing.responseStart,
    
    // DOM解析时间
    domParseTime: timing.domComplete - timi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值