Skip to content

Commit 745b48f

Browse files
committed
fix: 修复排名页组件的加载和卸载逻辑
当通过前端路由跳转到排名页面时,不会加载预测组件 因为原先只是通过`window.onload`来加载组件的 通过实现自定义的监听 url 改变事件 当 url 发生改变时,根据需要加载和卸载组件
1 parent 7514da3 commit 745b48f

File tree

3 files changed

+89
-39
lines changed

3 files changed

+89
-39
lines changed

src/content/pages/ranking/Item.tsx

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useEffect, useRef, useState } from 'react'
1+
import { FC, useEffect, useState } from 'react'
22

33
import { useGetPredictionQuery } from './rankSlice'
44

@@ -20,28 +20,14 @@ function getParam() {
2020
}
2121

2222
function useUrlChange() {
23-
const oldUrl = useRef(location.href)
2423
const [param, setParam] = useState(getParam())
2524
useEffect(() => {
26-
const body = document.querySelector('body')!
27-
28-
const observer = new MutationObserver(function (mutations) {
29-
mutations.forEach(function (_mutation) {
30-
if (oldUrl.current != location.href) {
31-
oldUrl.current = location.href
32-
setParam(getParam())
33-
}
34-
})
35-
})
36-
37-
const config = {
38-
childList: true,
39-
subtree: true,
25+
const handle = () => {
26+
setParam(getParam())
4027
}
41-
42-
observer.observe(body, config)
28+
window.addEventListener('afterurlchange', handle)
4329
return () => {
44-
observer.disconnect()
30+
window.removeEventListener('afterurlchange', handle)
4531
}
4632
}, [])
4733
useEffect(() => {
Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
import { StrictMode } from 'react'
2-
import { render } from 'react-dom'
2+
import ReactDom, { render } from 'react-dom'
33
import { Provider } from 'react-redux'
44

55
import { getElement } from '../../utils'
66
import Item from './Item'
77
import Title from './Title'
88

99
import store from '../../app/store'
10+
import { initUrlChangeEvent } from '../utils'
1011

11-
const reg = /https:\/\/leetcode-cn\.com\/contest\/([\d\D]+)\/ranking\//
12+
let nodes: HTMLTableCellElement[] = []
1213

1314
async function loadTitle() {
1415
const parent = await getElement('.table-responsive>table>thead>tr')
1516

1617
if (parent.length > 0) {
1718
const root = document.createElement('th')
19+
nodes.push(root)
1820
parent[0].append(root)
1921
render(
2022
<StrictMode>
@@ -25,26 +27,60 @@ async function loadTitle() {
2527
}
2628
}
2729

28-
if (reg.test(location.href)) {
29-
window.onload = async () => {
30-
loadTitle()
30+
async function loadPredictor() {
31+
loadTitle()
3132

32-
const trs = await getElement('.table-responsive>table>tbody>tr')
33-
34-
const start = trs[0].className === 'success' ? 1 : 0
35-
trs.forEach((tr, i) => {
36-
const root = document.createElement('td')
33+
const trs = await getElement('.table-responsive>table>tbody>tr')
34+
const start = trs[0].className === 'success' ? 1 : 0
35+
trs.forEach((tr, i) => {
36+
const root = document.createElement('td')
37+
nodes.push(root)
38+
render(
39+
<StrictMode>
40+
<Provider store={store}>
41+
<Item index={i - start} />
42+
</Provider>
43+
</StrictMode>,
44+
root
45+
)
3746

38-
render(
39-
<StrictMode>
40-
<Provider store={store}>
41-
<Item index={i - start} />
42-
</Provider>
43-
</StrictMode>,
44-
root
45-
)
47+
tr.append(root)
48+
})
49+
}
4650

47-
tr.append(root)
48-
})
51+
const urlMatchReg = /https:\/\/leetcode-cn\.com\/contest\/([\d\D]+)\/ranking\//
52+
window.onload = () => {
53+
if (urlMatchReg.test(location.href)) {
54+
loadPredictor()
4955
}
5056
}
57+
58+
initUrlChangeEvent()
59+
60+
window.addEventListener('urlchange', function () {
61+
/**
62+
* url 变化,可能会有四种情况:
63+
* 1. 从不匹配的地址跳转到匹配的地址
64+
* 2. 从匹配的地址跳转到不匹配的地址
65+
* 3. 从匹配的地址跳转到不匹配的地址
66+
* 4. 从不匹配的地址跳转到不匹配的地址
67+
*
68+
* 其中需要做处理的是
69+
* 第一种情况需要加载组件
70+
* 第二种情况需要卸载组件
71+
* 而第三第四种清理可以不用处理
72+
*/
73+
74+
if (!urlMatchReg.test(location.href)) {
75+
// 从排名页跳转到比赛主页
76+
nodes.forEach(node => ReactDom.unmountComponentAtNode(node))
77+
nodes = []
78+
} else {
79+
// 从主页跳转到排名页
80+
if (nodes.length === 0) {
81+
loadPredictor()
82+
} else {
83+
window.dispatchEvent(new Event('afterurlchange'))
84+
}
85+
}
86+
})

src/content/pages/utils.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// 添加监听 url 变化的事件
2+
const initUrlChangeEvent = (() => {
3+
let isLoad = false
4+
const load = () => {
5+
if (isLoad) return
6+
isLoad = true
7+
8+
const oldPushState = history.pushState
9+
const oldReplaceState = history.replaceState
10+
11+
history.pushState = function pushState(...args) {
12+
oldPushState.apply(window, args)
13+
window.dispatchEvent(new Event('urlchange'))
14+
}
15+
16+
history.replaceState = function replaceState(...args) {
17+
oldReplaceState.apply(window, args)
18+
window.dispatchEvent(new Event('urlchange'))
19+
}
20+
21+
window.addEventListener('popstate', () => {
22+
window.dispatchEvent(new Event('urlchange'))
23+
})
24+
}
25+
return load
26+
})()
27+
28+
export { initUrlChangeEvent }

0 commit comments

Comments
 (0)