个人文档
  • AI编程Cursor
  • GPT使用笔记
  • npm常用库合集
  • 同步用
  • 小Demo们
  • 工具网站教程集合
  • HTML、CSS 工具方法集合
    • HTML 全局属性
    • css常用功能
    • font-face 字体|子集相关
    • iframe父子页面传值
    • input输入优化
    • loading状态
    • nodejs使用谷歌邮箱发邮件
    • 为 Dom 自定义事件监听
    • 初始html的head标签配置
    • 拼音输入中文汉字的事件监听
    • 文字颜色效果
    • 文档片段范围 Range
    • 移动端开发-rem
    • 等宽字体推荐
    • 网站SEO优化注意点
    • 邮件html模板
  • JS 工具方法集合
    • Axios 简单使用
    • Axios 简单封装
    • Gitbook的安装和使用
    • Github 登录开发
    • HTML转为纯文本
    • JS 中强大的操作符
    • cookie 操作
    • js 动态加载js资源
    • js 常用功能语句
    • js取代trycatch的方法封装
    • js接口下载二进制
    • script 标签的异步属性
    • 判断当前是移动端还是pc端
    • 刷新token队列管理
    • 前端多线程 Web Worker
    • 加密-AES对称加密
    • 加密-node进行rsa加密解密
    • 地区省市区三级联动的地址数据 + 功能
    • 复制插件
    • 开发时环境变量
    • 得到随机图片
    • 数字格式整理集合
    • 数学计算插件
    • 时间格式整理
    • 获取ip地址
    • 获取url传参
    • 进制转换和位运算符
    • 页面隐藏|激活|关闭的监听
  • JS 知识点研究
    • Babel 历史和原理
    • Babel 配置和使用
    • Function 的 apply、call、bind
    • HTTP浏览器缓存粗解
    • Source map 文件还原为源码
    • TS常用技巧
    • js 的加载和模块化
    • js 的新数据类型 Symbol
    • js的代理对象 proxy 和 defineProperty
    • js的原型链 prototype
    • vite 打包体积优化
    • webpack 可视化打包文件大小插件
    • webpack 基础使用配置
    • webpack 版本5的报错
    • yeoman 开发脚手架的工具
    • 同步异步和微任务宏任务
    • 移动端调试---谷歌工具+eruda+vconsole
    • 转换-Blob URL
    • 转换-FileReader
    • 转换-Js文件类型和转换
    • 转换-前端开发的URL的编码和解码
    • 转换-字符串和Base 64的转换
  • Node 和 Npm 相关
    • Node 开发环境配置
    • express + jwt 校验
    • node 常用方法
    • node后台服务器-PM2
    • node基本使用
    • npm 中依赖的版本问题
    • npm 功能使用
    • npm指令说明和其他对比
    • nvm版本管理+自动切换node版本
  • React 学习
    • React Hook
    • React 项目基础开发
    • React.memo 和 React.PureComponent
    • React懒加载进阶
    • useContext Hook
    • useEffect Hook
    • useMemo 和 useCallback - Hook
    • useRef Hook
    • useState Hook
    • 同步修改变量功能封装 useVal for react
    • 轻便的传值组件
  • Rust 语言相关
    • Rust 基本
    • Rust 基础学习
    • Rust 调用 Object-C 的API
    • Tauri 基本使用
    • Tauri 是什么
  • VUE 学习
    • Vue3 使用
    • Vue3使用hook
    • Vue开发小技术点
    • vue路由切换时的动画效果
    • 花式引入组件和资源-打包时拆包减少js体积
  • Web3相关
    • Web3.0开发上-准备和概念理解
    • Web3.0开发下-功能代码示例
    • 以太坊区块链和Web3.0
    • 开发智能合约
  • python
    • pyenv版本管理工具
    • python初始化
    • python基本概念
    • venv虚拟环境
  • 个人其他
    • Steam Deck的基本设置和插件
  • 其他编程相关
    • Git教程和常用命令
    • Java开发-JDK和Maven的安装和卸载
    • Jenkins安装和基本使用
    • Linux系统指令
    • Mac 使用2K屏幕开启缩放
    • Mac 使用VS code打开项目
    • Mac 安装 Homebrew
    • Mac 的终端 shell 与 zsh
    • Mac 软件和插件
    • MacBook使用建议
    • Mac升降级到指定版本的系统
    • Mac安装Zsh
    • Mac安装软件各种提示
    • Mac系统脚本语言 AppleScript 的使用
    • Mac终端代理工具
    • Markdown(md)文档开发-Typora
    • Mysql 的安装和使用
    • Nginx 安装和基础使用
    • Nginx 稍微高深的配置
    • Slate - Api 的文档开发工具
    • Sublime配置
    • Ubuntu的 apt-get 使用
    • VScode配置
    • Windows 软件和插件
    • curl 工具使用
    • github 网站访问优化
    • host 文件
    • inquirer 终端中和用户交互
    • uTools的插件开发教程
    • vim 文本编辑功能
    • 使用 Github Pages 免费部署网站
    • 压缩指令 zip 和 unzip
    • 油猴的安装和开发(Tampermonkey)
    • 阿里云简略使用
  • 微信开发
    • 微信小程序开发
    • 微信开发必读
    • 微信开发提前购买域名
    • 微信手机打开的页面中授权登录
    • 微信扫码登录
    • 微信服务号登录+推送服务提醒
    • 自定义分享卡片-node.js实现
  • 数据结构与算法
    • KMP算法
    • Wildcard字符串分析算法
    • 二叉树
    • 字典树
    • 时间复杂度浅析
    • 算法神器——动态规划
Powered by GitBook
On this page

Was this helpful?

  1. JS 工具方法集合

页面隐藏|激活|关闭的监听

title: 页面隐藏|激活|关闭的监听 id: 41fdefb4b2b347fc713f68f48b8d0881 tags: [] date: 2000/01/01 00:00:00 updated: 2022/12/09 13:40:03 isPublic: true --#|[分隔]|#--

页面隐藏|激活|关闭的监听

当开发了一个包含轮询调用接口、socket推送后实时渲染数据、持续性动画的页面时,上线后可能会出现性能问题,或者用户离开页面一段时间后,浏览器为了节省资源,会对我们的页面进行cpu、网络方面的限制,导致用户再回到页面,页面卡死或直接崩溃。

与其等浏览器把我们干死,不如我们自己只能休眠。

下面这个插件可以监听用户切换到别的页面、重新回来的事件。

可以看这个Demo,打开页面,然后切换到其他页面再回来,查看页签标题和页面中打印的信息,页面监听事件还有次数逻辑,可以看demo页面的源代码了解一下。

查看Demo

// 引入
import PageWatch from './PageWatch';

// 要绑定监听的事件对象组装(下面三个字段不是必传)
let bindEvents = {
  visible: (pageWatchObj) => {}, // 回来的回调方法
  hidden: (pageWatchObj) => {}, // 离开的回调方法
  reload: (pageWatchObj) => {}, // 即将刷新页面的回调方法
}

// 监听事件绑定成功的事件(可以不用)
let bindSuccess = () => {}

// 实例化对象
new PageWatch(bindEvents, bindSuccess)
// PageWatch.js

// 绑定激活和离开的方法
export default class PageWatch {
  success = undefined // 切换一次的回调函数
  status = undefined // 当前的状态
  visibleNum = undefined // 离开的次数
  hiddenNum = undefined // 归来的次数
  _prefix = undefined // 前缀
  _eventName = undefined // 浏览器监听事件的事件名,可能需要加前缀
  _attributeName = undefined // 浏览器获取当前状态的事件名,可能需要加前缀
  _nowEvent = undefined // 当前绑定的归来或离开的事件们
  constructor(objData, success) {
    this.status = undefined
    this.visibleNum = undefined
    this.hiddenNum = undefined
    this._prefix = undefined
    this._eventName = undefined
    this._attributeName = undefined
    this._nowEvent = undefined
    this.init(objData)
    this.success = success
  }
  init(eventObj) {
    this.status = undefined
    this.visibleNum = 0
    this.hiddenNum = 0
    this._nowEvent = {}
    // 判断浏览器是否支持
    this._prefix = null // 前缀
    if ('hidden' in document) this._prefix = '';
    else {
      let prefixes = ['webkit', 'moz', 'ms', 'o'];
      for (let i = 0; i < prefixes.length; i++) {
        if ((prefixes[i] + 'Hidden') in document)
          this._prefix = prefixes[i]
        break
      }
    }
    let obj = { // 记录浏览器支持情况
      reload: true,
      visible: true,
      hidden: true
    }
    if (this._prefix === null) {
      obj.visible = false
      obj.hidden = false
    }
    this._eventName = (this._prefix ? this._prefix + 'Hidden' : 'hidden').replace(/[H|h]idden/, '') + 'visibilitychange';
    this._attributeName = this._prefix ? this._prefix + 'VisibilityState' : 'visibilityState';
    // 如果初始化时传入了事件对象
    if (typeof (eventObj) === 'object' && Array.isArray(eventObj) === false) this.add(eventObj)
    this.eventChange.updataEvent(obj) // 监听事件,一直监听
    this.success && this.success(obj)
  }
  // 移除事件监听
  removeEvent() {
    this.eventChange.removeEvent()
  }
  add(eventObj) {
    if (!(typeof (eventObj) === 'object' && Array.isArray(eventObj) === false)) return new Error(eventObj, ' 不是对象')
    // 更新要绑定的事件
    for (let key in eventObj) {
      if (key === 'visible' || key === 'hidden' || key === 'reload') {
        this._nowEvent[key] = eventObj[key]
      }
    }
  }
  // this.remove 需要的字符串判断和处理函数
  _remove_handle(string) {
    if (string === 'visible' || string === 'hidden' || string === 'reload') {
      delete this._nowEvent[string]
    }
  }
  remove(eventNames) {
    if (typeof (eventNames) !== 'string' && Array.isArray(eventNames) !== true) return new Error(eventNames, ' 不是 string 且不是 array')
    // 更新要绑定的事件
    if (typeof (eventNames) === 'string') this._remove_handle(eventNames)
    else if (Array.isArray(eventNames)) {
      for (let i = 0; i < eventNames.length; i++) {
        this._remove_handle(eventNames[i])
      }
    }
  }
  // 内部更新事件
  eventChange = ((__this) => {
    // console.log(_this)
    const _this = __this || {}
    const inside_event = {
      hidden() {
        this.hiddenNum++ // 更新离开的次数
        this.status = 'hidden'
        _this._nowEvent.hidden && _this._nowEvent.hidden(_this)
      },
      visible() {
        _this.visibleNum++ // 更新归来的次数
        _this.status = 'visible'
        _this._nowEvent.visible && _this._nowEvent.visible(_this)
      },
      reload: function (e) {
        if (!_this._nowEvent.reload) return false
        let needTip = {} // 用于判断是否需要浏览器弹窗提醒
        _this._nowEvent.reload && _this._nowEvent.reload(_this, needTip)
        // 判断是否需要浏览器弹窗提醒
        if (typeof(needTip) === 'object') {
          let bool = false
          for (let key in needTip) {
            if (needTip[key]) {
              bool = true
              break
            }
          }
          // 需要阻止
          if (bool) {
            // eslint-disable-next-line
            let confirmationMessage = "\o/";
            (e || window.event).returnValue = confirmationMessage;     // Gecko and Trident
            return confirmationMessage;  
          }
        }
      }
    }
    // 监听到页面前后台切换发生了变化
    let insideFn_show = () => {
      inside_event[document[_this._attributeName]]()
    }
    // 监听到页面更新了
    let insideFn_reload = () => {
      inside_event['reload']()
    }
    return {
      updataEvent(obj) {
        obj.visible && document.addEventListener(_this._eventName, insideFn_show, false)
        window.addEventListener('beforeunload', insideFn_reload, false)
      },
      removeEvent() {
        document.removeEventListener(_this._eventName, insideFn_show, false)
        window.removeEventListener('beforeunload', insideFn_reload, false)
      }
    }
  })(this)
}
Previous进制转换和位运算符NextJS 知识点研究

Last updated 3 months ago

Was this helpful?