react-router 的API及原理

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 事件来监听变化,从而做出相应的视图变化。

  1. <BrowserRouter>包裹整个App系统
  2. Route匹配相应的location的地址,匹配成功后渲染组件
  3. 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

借鉴文章

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值