Vue项目中index.html中监听页面变化

前言

在对接3D可视化的时候,只要页面发生变化,回调就失效了,所以要监听页面变化,添加回调事件。

监听路由变化

这种方式只有路由发生变化后才调用,更合适一点,但是要注意页面加载完毕。

这种方式有时依旧会出现注册的事件消失的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const originalPushState = history.pushState
const originalReplaceState = history.replaceState

// 统一处理路由变化的函数
async function handleRouteChange() {
console.log('路由变化:', window.location.href)
await new Promise((resolve) => setTimeout(resolve, 100))
pageChange()
}

// 重写 pushState
history.pushState = function (...args) {
originalPushState.apply(history, args)
handleRouteChange() // 路由变化时触发
}

// 重写 replaceState
history.replaceState = function (...args) {
originalReplaceState.apply(history, args)
handleRouteChange() // 路由变化时触发
}

// 监听浏览器前进/后退(会触发 popstate)
window.addEventListener('popstate', handleRouteChange)

监听页面变化

这种方式页面只要有微小的变动就会触发回调,触发频率较高,并且比较浪费性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
document.addEventListener('DOMContentLoaded', function () {
// 创建一个观察者对象
const observer = new MutationObserver(function (mutations, observer) {
if (mutations[0].target.innerHTML !== mutations[0].oldValue) {
pageChange()
}
})

// 观察body元素的变化
const body = document.querySelector('body')
if (body) {
const config = {
childList: true, // 监听子节点变化
attributes: true, // 监听属性变化
subtree: true, // 包括后代节点
attributeOldValue: true // 记录属性旧值
}
observer.observe(body, config)
}
})

注意

直接观察 body 并开启 subtree: true 通常会比较浪费性能,尤其是在复杂页面或动态内容较多的场景下。

定时任务

在对接3D可视化的时候,厂家给的方式是监听body,进行事件的添加,但是这样性能非常不好,监听DOM的性能浪费要比定时任务大多了。

所以最终使用定时任务来实现。

1
2
3
4
5
6
7
8
9
10
11
12
function addUeListener() {
if (window.ueInter) {
clearInterval(window.ueInter)
}
window.ueInter = setInterval(() => {
pageChange()
}, 2000)
}

document.addEventListener('DOMContentLoaded', function () {
addUeListener()
})