马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
2022 北京冬奥会开幕式 此前不绝在迷惑,显着 pushState()、replaceState() 不触发 popstate 事故,可为什么 React Router 还能挂载对应路由的组件呢?
翻了一下 history.js 源码,终于知道缘故起因了。
源码
假设项目路由计划如下:
- import { render } from 'react-dom'
- import { BrowserRouter, Routes, Route } from 'react-router-dom'
- import { Mine, About } from './routes'
- import App from './App'
- const rootElement = document.getElementById('root')
- render(
- <BrowserRouter>
- <Routes>
- <Route path="/" exact element={<App />} />
- <Route path="/mine" element={<Mine />} />
- <Route path="/about" element={<About />} />
- </Routes>
- </BrowserRouter>,
- rootElement
- )
复制代码 然后我们看下 <BrowserRouter /> 的源码(react-router-dom/modules/BrowserRouter.js),以下省略了一部门无关代码:
- import React from 'react'
- import { Router } from 'react-router'
- import { createBrowserHistory as createHistory } from 'history'
- /**
- * The public API for a <Router> that uses HTML5 history.
- */
- class BrowserRouter extends React.Component {
- // 构建 history 对象
- history = createHistory(this.props)
- render() {
- // 将 history 对象等传入 <Router /> 组件
- return <Router history={this.history} children={this.props.children} />
- }
- }
- // ...
- export default BrowserRouter
复制代码 接着我们继续看下 <Router /> 组件的源码(react-router/modules/Router.js),如下:
- import React from 'react'
- import HistoryContext from './HistoryContext.js'
- import RouterContext from './RouterContext.js'
- /**
- * The public API for putting history on context.
- */
- class Router extends React.Component {
- static computeRootMatch(pathname) {
- return { path: '/', url: '/', params: {}, isExact: pathname === '/' }
- }
- constructor(props) {
- super(props)
- this.state = {
- location: props.history.location
- }
-
- // 关键点:
- // 当触发 popstate 事件、
- // 或主动调用 props.history.push()、props.history.replace() 方法时,
- // 都会执行 history 对象的 listen 方法,使得执行 setState 强制更新当前组件
- this.unlisten = props.history.listen(location => {
- this.setState({ location })
- })
- }
- componentWillUnmount() {
- // 组件卸载时,解除监听
- if
复制代码 |