BOM

浏览器行为控制

Posted by page on June 9, 2021

BOM

location

location.reload:重载页面,传入参数值 true 将强制禁用缓存重载;

location.replace:替换页面加载URL;

注: 调用 location 加载须确保不被多次调用,否则调用会覆盖,且导致不可预知错误;

devicePixelRatio

物理像素:显示屏的物理像素点,与分辨率相关

CSS像素:用于显示图像的最小渲染单位;

设备像素比:当前显示设备的物理像素分辨率与CSS 像素分辨率之比;

显示计算:

  • 原图像像素信息:以300x300px的原图片文件为例,即图片包含了300x300个物理像素点的信息;

  • CSS像素信息:CSS像素点由CSS宽高决定,未设置则为原图片size,即此时需300x300个CSS像素;在标准屏则将占用300x300个物理像素;2倍屏则占用600x600个物理像素;

  • CSS宽高控制:

    • 若设置了图片的CSS宽高,如100x100px,即100x100个渲染单位,即在标准屏则将用100x100个物理像素显示300x300像素点信息;2倍屏则占用200x200个物理像素显示300x300个像素信息;前者像素信息在被计算显示后产生部分丢失,导致模糊,2倍图就是解决这种情况;

    • 若设置了图片的CSS宽高,如800x800px,即在标准屏则将用800x800个物理像素显示300x300像素点信息;2倍屏则占用1600x1600个物理像素显示300x300个像素信息;此时图片被放大,导致都会产生模糊;

行为

浏览器回退

监听浏览器回退到当前页面后,执行提示、弹窗、请求等操作

浏览器回退行为

  • PC 浏览器与微信 webview:回退后立即会通过刷新重开一个新的页面副本
  • 部分手机内置浏览器:回退后页面即离开时页面,即原文档状态从未改变,会话未关闭过(页面跳转只是新开个标签页)
  • 第三方浏览器:回退时读取缓存的 html 文件,即原文档状态未改变,但会话关闭过

注: 在微信页面回退时并不需要额外添加初始化处理,因为回退页面会自动重新执行(且重新执行中原页面发出请求会被(blocked)

popstate

HTML5 中 history 的新 API 之一,使用 history.pushState() 为单页面伪造一个历史记录状态(必须在有交互时);当单页面的历史记录状态改变时,触发 window.popstate 事件;

btn.addEventListener("click", function () {
  // 修改页面历史记录状态
  history.pushState({ ...stateData }, null, "#otherPage");
});

window.addEventListener("popstate", function () {
  if (!stateData || !location.hash) {
    // ...页面状态回退处理
  }
});

popstate 监听页面回退仅支持单页面内部历史记录状态回退,不作用于浏览器历史记录回退;

visibilitychange

监听页面可见属性改变,可用于判断页面标签、页面前/后台、屏幕休眠/显示切换;

window.isLeaved = false; // 记录页面是否处于已离开状态

btn.addEventListener("click", function () {
  // 离开页面事件
  window.willLeave = true; // 记录页面将要离开
  location.href = "https://www.baidu.com";
});

document.addEventListener("visibilitychange", (e) => {
  let v = document.visibilityState;
  if (v == "visible" && window.isLeaved) {
     // 页面从不可见变为可见 判断是否为页面回退的情况
     window.isLeaved = false;
     // ... 页面回退处理
  } else if(v == "hidden" && window.willLeave) {
    // 页面从可见变不可见 判断是否为页面离开情况
    window.isLeaved = true; // 记录页面处于离开状态
    window.willLeave = false;
  }
});

visibilitychange 事件在页面可见性改变时触发,首次加载时不会触发的;

部分第三方浏览器中,页面被回退后从缓存中读取页面,原页面的 visibilitychange 不被触发;微信中页面回退直接刷新原页面,仅在ios下执行;

pageshow

监听页面完整显示,load 事件后执行;event.persisted 用于判断是否读取缓存来显示页面;

window.historyPageMark = false; // 标记是否为历史页面
const onPageBack = function(callback){
  window.addEventListener("pageshow",e => {
    console.log(window.historyPageMark,e.persisted,isEnterByBack());
    if(window.historyPageMark === true || e.persisted || isEnterByBack()){
      callback();
    }
    window.historyPageMark = true;  // 首次pageshow执行后更新标记为历史页面
  })
}
function isEnterByBack(){ // 判断页面进入类型是否为回退
  if(!window.performance) 
    return false;
  if(window.performance.getEntriesByType("navigation")[0]) 
    return window.performance.getEntriesByType("navigation")[0].type === "back_forward";
  if(window.performance.navigation)
    return window.performance.navigation.type === 2;
  return false;
}

监听页面的pageshow事件;页面回退时,对3个值进行判断

  1. window.historyPageMark:该标记值为true,则页面被打开过,此次pageshow为页面回退触发
  2. event.persisted:浏览器从缓存中读取页面后显示,符合页面回退情况
  3. window.performance:借助BOM对象performance的navigation状态判断页面进入类型,包括导航,刷新,回退;判断是否为回退进入

总结: popstate 监听页面内前进回退,visibilitychange 监听分享等界面切换,pageshow 监听从其它界面/页面回退至本页;