vue页面中的window.onhashchange事件无法触发分析

ops/2024/10/18 8:20:08/

一、需求

对某个使用了Vue框架的页面,编写一些脚本操作修改DOM元素。需求之一就是监听URL地址变化,例如:从http://localhost:8080/#/abc切换到http://localhost:8080/#/def。URL有变化就触发执行某些操作。

二、问题

一般来说,监听window的hashchange事件就可以了。例如:

window.onhashchange = function(event) {// 当location变化时,这个函数会被调用console.log("Location changed:", window.location.href);
};

当使用window.location.hash = path;修改hash时,会触发。

但是用了Vue-router的网页就不一定行了。因为Vue的处理逻辑是:hash模式下符合条件时调用的实际上是pushState方法,而pushState和replaceState是无法触发onhashchange事件的,导致无法被监听到。
以下是Vue-router源码情况:

function pushState (url, replace) {saveScrollPosition();// try...catch the pushState call to get around Safari// DOM Exception 18 where it limits to 100 pushState callsvar history = window.history;try {if (replace) {history.replaceState({ key: _key }, '', url);} else {_key = genKey();history.pushState({ key: _key }, '', url);}} catch (e) {window.location[replace ? 'replace' : 'assign'](url);}
}
...
function pushHash (path) { // this.$router.push时触发if (supportsPushState) {pushState(getUrl(path));} else {window.location.hash = path;}
}
...

可以看到如果支持 pushState,就使用 pushState,而不是调用 window.location.hash = path;

解决方法

重写并覆盖原有的 pushStatereplaceState 方法,然后手动触发 hashchange 事件。

// 保存原始的 pushState() 方法的引用
var historyPushState = history.pushState;
// 封装 pushState() 方法
function myPushState(state, title, url) {// 调用原生的 pushState() 方法historyPushState.call(history, state, title, url);// 手动触发 hashchange 事件console.log('由pushState()手动触发事件');window.dispatchEvent(new HashChangeEvent("hashchange"));
}
// 重新定义 history.pushState() 方法
Object.defineProperty(history, 'pushState', {value: myPushState});// 保存原始的 replaceState() 方法的引用
var historyReplaceState = history.replaceState;
// 封装 replaceState() 方法
function myReplaceState(state, title, url) {// 调用原生的 replaceState() 方法historyReplaceState.call(history, state, title, url);// 手动触发 hashchange 事件console.log('由replaceState()手动触发事件');window.dispatchEvent(new HashChangeEvent("hashchange"));
}
// 重新定义 history.replaceState() 方法
Object.defineProperty(history, 'replaceState', {value: myReplaceState});// 监听URL地址变化
window.onhashchange = function(event) {// 当location变化时,这个函数会被调用console.log("Location changed:", window.location.href);
};

http://www.ppmy.cn/ops/42035.html

相关文章

吴恩达深度学习笔记:优化算法 (Optimization algorithms)2.9-2.10

目录 第二门课: 改善深层神经网络:超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第二周:优化算法 (Optimization algorithms)2.9 学习率衰减(Learning rate decay) 第二门…

数据缓存,可以尝试RocksDB了

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 个人IP:shigen shigen在最近的学习中,接触到了一款新的缓存数据库RocksDB&#xff…

STC8增强型单片机开发——串口调试UART

一、什么是串口 串口是一种在数据通讯中广泛使用的通讯接口,通常我们叫做UART (通用异步收发传输器Universal Asynchronous Receiver/Transmitter),其具有数据传输速度稳定、可靠性高、适用范围广等优点。在嵌入式系统中,串口常用于与外部设备…

基于 Spring Boot 博客系统开发(八)

基于 Spring Boot 博客系统开发(八) 本系统是简易的个人博客系统开发,为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。🌿🌿🌿 基于 Spring Boot 博客系统开发(七)&#x1f…

react的多级路由定义

在写实验室项目的时候,有一个需求,在二级路由页面点击按钮,跳转到详情列表页面,同时三级路由不用在导航栏显示,效果图如下: 前期的尝试: 在route,js文件这样定义的: {path: music,…

韵搜坊 -- java爬虫抓取数据

文章目录 三种抓取方式数据抓取的流程获取文章具体操作 获取用户获取图片jsoup操作 三种抓取方式 直接调用请求接口(最方便,这里使用该方法) HttpClient,OKHttp,RestTemplate,Hutool等网页渲染出明文内容后,从前端页面的内容抓取有些网站可能是动态请求…

Spark SQL

一、简介 Spark SQL 是 Spark 用于结构化数据(structured data)处理的 Spark 模块。 1.特点: ➢ 数据兼容方面 SparkSQL 不但兼容 Hive,还可以从 RDD、parquet 文件、JSON 文件中获取数据,未来版本甚至支持获取 RDBMS 数据以及 cassandra 等 NOSQL 数据…

Docker 中快速构建 Redis Cluster 集群

Docker 中快速构建 Redis Cluster 集群 目录 前言环境准备 所需软件配置网络 构建 Redis Cluster 镜像 创建自定义 Dockerfile构建镜像 启动 Redis 节点容器 启动命令 配置 Redis Cluster 集群 创建 Redis 集群验证集群状态 总结 前言 Redis 是一个高性能的键值对数据库&am…