HTML5的方法
底层是history来实现的(go, back, forward),html5的History对其进行一层包装,暴露了新的API给我们。
pushState()
:
replaceState()
:
replaceState()和pushState()区别:pushState是压入浏览器的会话历史栈中,会使得History.length加1,而replaceState是替换当前的这条会话历史,因此不会增加History.length.
配合window.onpopstate
来使用:每当活动的历史记录项发生变化时, popstate 事件都会被传递给window对象。如果当前活动的历史记录项是被 pushState 创建的,或者是由 replaceState 改变的,那么 popstate 事件的状态属性 state 会包含一个当前历史记录状态对象的拷贝。
react-router就是控制不同的url渲染不同的组件。react-router在history库的基础上,实现了URL与UI的同步。
react-router 本质上,利用了 history api 的 pushState, replaceState 方法来控制路由地址,然后使用 popstate, hashchange 事件来监听变化,从而做出相应的视图变化。
<BrowserRouter>
包裹整个App系统Route
匹配相应的location的地址,匹配成功后渲染组件Link
决定的是如何在页面内改变url,点击后会传一个prop给组件
react-router主要是通过html5的history
function createHistory(options={}) {
...
return {
listenBefore, // 内部的hook机制,可以在location发生变化前执行某些行为,AOP的实现
listen, // location发生改变时触发回调
transitionTo, // 执行location的改变
push, // 改变location
replace,
go,
goBack,
goForward,
createKey, // 创建location的key,用于唯一标示该location,是随机生成的
createPath,
createHref,
createLocation, // 创建location
}
}
Router
摘录核心代码
class Router extends React.Component {
static computeRootMatch(pathname) {
return { path: "/", url: "/", params: {}, isExact: pathname === "/" };
}
constructor(props) {
super(props);
this.state = {
location: props.history.location
};
//判断是否挂载组件,挂载后变为true
this._isMounted = false;
//
this._pendingLocation = null;
/*外层组件调用Router时默认传递props
props:staticContext:
history:当前所在的路由
children:孩子组件
*/
if (!props.staticContext) {
/*
只要不是静态路由,则会对location进行监听,
只要location发生变化,就会调用listen方法,内部调用setState更新路由。
*/
this.unlisten = props.history.listen(location => {
if (this._isMounted) {
this.setState({ location });
} else {
this._pendingLocation = location;
}
});
}
}
componentDidMount() {
this._isMounted = true;
if (this._pendingLocation) {
this.setState({ location: this._pendingLocation });
}
}
componentWillUnmount() {
if (this.unlisten) this.unlisten();
}
render() {
return (
<RouterContext.Provider
children={this.props.children || null}
value={{
history: this.props.history,
location: this.state.location,
match: Router.computeRootMatch(this.state.location.pathname),
staticContext: this.props.staticContext
}}
/>
);
}
}
Route
Re
借鉴文章