美文网首页
react-router-dom实现原理

react-router-dom实现原理

作者: 祝家庄打烊 | 来源:发表于2020-02-12 13:58 被阅读0次

语法分析(react-router-dom)

一、安装react-router-dom
npm install react-router-dom --save-dev
二、在根组件上配置路由,引用react-router-dom结构{ HashRouter as Router, Route ,Link ,Redirect ,Switch },HashRouter组件是路由的根组件,定义属性和方法传递给子组件。Router组件进行路由,指定每个路由跳转到相应的组件。Link组件指定跳转链接。Redirect组件路由重定向,不管什么情况下,都会跳转当前指定的路径,和switch组件联合起来一起调用,当路径匹配到路由,不在往下匹配。

import React from 'react';
import './App.css';
import { HashRouter as Router, Route ,Link ,Redirect ,Switch } from './react-router-dom'
import Home from "./view/Home";
import Profile from "./view/Profile";
import Detail from "./view/Detail";

function App() {
  return (
    <div className="App">
      <Router>
        <div>
          <div>
            <Link to="/">首页</Link>
            <Link to="/profile">主页</Link>
            <Link to="/detail">详情页</Link>
          </div>
          <div>
            <Switch>
              <Route path="/home" exact component={Home}></Route>
              <Route path="/profile" exact component={Profile}></Route>
              <Route path="/detail" exact component={Detail}></Route>
              <Redirect to="/home"></Redirect>
            </Switch>
          </div>
        </div>
      </Router>
    </div>
  );
}
export default App;

实现react-router-dom

一、首先了解HashRouter和HistoryRouter的区别,HashRouter是根据路径"#"后面参数进行匹配路由,在服务器上匹配的路径,始终只有一个。HistoryRouter是根据"/"后面的参数匹配路由,在服务器上会匹配多个路由地址,在服务器上并不会存在这些地址,报错404。
二、HashRouter定义状态,状态存储默认pathname哈希值和push方法路由跳转。

componentDidMount(){
    let _that = this;
    window.location.hash = window.location.hash || "/";
    window.addEventListener("hashchange",function(){
        _that.setState({
            ..._that.state,
            location:{
                ..._that.state.location,
                pathname: window.location.hash.slice(1) || "/"
            }
        })
    })
}

三、HashRouter根组件上状态传递给子组件,用到react16的新属性React.createContext()

import React from 'react';
let {Provider ,Consumer} = React.createContext();
export {Provider ,Consumer};

四、Route组件进行路由匹配,匹配到哪个组件,进行渲染,pathToRegexp模块可以匹配链接地址的多个层级。

render(){
    let {path ,component:Component} = this.props;
    return <Consumer>
        {(state)=>{
            let exact = this.props.exact || false;
            let reg = pathToRegexp(path,[],{end:exact});
            let {pathname} = state.location;
            if(reg.test(pathname)){
                return <Component {...state}></Component>;
            }
            return null;
        }}
    </Consumer>
}

五、Link和Redirect组件指定元素的click事件,调用根组件push方法跳转。

render(){
   return <Consumer>
        {(state)=>{
            return <a onClick={()=>state.history.push(this.props.to)}>
                {this.props.children}
            </a>
        }}
   </Consumer>
}

六、Switch组件遍历子组件的pathname是否等于地址栏的哈希值,只有相等,才返回当前组件,Redirect组件除外。

render(){
   return <Consumer>
        {(state)=>{
            let exact = false;
            let pathname = state.location.pathname;
            let children = this.props.children
            for(var i=0;i<children.length;i++){
                let child = children[i];
                let path = child.props.path || '';
                let reg = pathToRegexp(path,[],{end:exact});
                if(reg.test(pathname)){
                    return child;
                }
            };
            return null;
        }}
    </Consumer>
}

项目案例

相关文章

网友评论

      本文标题:react-router-dom实现原理

      本文链接:https://www.haomeiwen.com/subject/plnqfhtx.html