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

一、需求

对某个使用了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 calls
  var 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);
};

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值