cognitive

Before the separation of the front and back ends, routing was almost for the background. It was said that controlling the routing was equivalent to occupying a sovereign position, which I think is not an exaggeration. Routing determines where your pages come from and where they go. React router router router router Router Router Router Router Router Router Router Router Router Router Router Router Router Router

choose

what’s the diff between react-router-dom & react-router? # 4648

HashRouter

This paper still uses the model of test-driven development to straighten out the idea… Begin…

  1. Render three different components based on different routes (Home,News,About)
letHome = () => <div>letNews => <div> News </div>;letAbout = () => <div>Copy the code

Rendering method:

ReactDOM.render(
    <Router>
        <Route path='/home' component={Home}></Route>
        <Route path='/news' component={News}></Route>
        <Route path='/about component={About}> , document.querySelector('#app')
)

Copy the code

Useful parameters are observed by passing parameters as follows (Figure 1)

let Home = (props,context)=> {
    console.log(props)
    returnThe < div > home page < / div >; }Copy the code

 {
  history:{
    push()
  },
  location:{pathname:'/home'},
  match{
    params:{},
    path:'/home',
    url:'/home'}}Copy the code

Write a parent component, hashrouter.js, and a single Route, route.js hashrouter.js: Listens for the Hashchange event, i.e., rerender the page, while the component is mounted

componentWillMount(){
    window.location.hash = window.location.hash || '/';
    let render = ()=>{
        this.setState({});
    }
    window.addEventListener('hashchange',render);
}
Copy the code

Parent and child components communicate via context, passing the location. pathName value

static childContextTypes = {
    location:PropTypes.object
}
constructor(props){
    super(props);
    this.state = {};
}
getChildContext() {return {
        location:{pathname:window.location.hash.slice(1)||'/'}}}Copy the code

A HashRouter renders objects as child components and has nothing to render itself.

render() {return this.props.children;
}
Copy the code

Route.js: Gets the pathname of the context and compares it to the path passed in by the component to see if it is equal. If it is equal, render the Component passed in as props

static contextTypes = {
    location: PropTypes.object
}
render() {let {path,component:Component} = this.props;
    let {location:{pathname}} = this.context;
    if(path == pathname || pathname.startsWith(path)){
        return <Component location={this.context.location} history={this.context.history}/>;
    }
    return null;
}
Copy the code

To change the hash value entered by the browser, you can switch to different components and display different content. 2. In the form of navigation, click the navigation bar of the page to switch to a different page (Link component). Click change hash by context history.

HashRouter:
static childContextTypes = {
    location:PropTypes.object
}
getChildContext() {return {
        location:{pathname:window.location.hash.slice(1)||'/'},
        history:{ push(path){ window.location.hash = path; }}}}Copy the code

Link.js

import React,{Component} from 'react';
import ProTypes from 'prop-types';
export default class Link extends Component{
    static contextTypes = {
        history:ProTypes.object
    }
    render() {return (
            // <a href={"#"+this.props.to}>{this.props.children}</a>
            <a onClick={()=>this.context.history.push(this.props.to)}>{this.props.children}</a>
        )
    }
}
Copy the code

Call:

<ul className='nav navbar-nav'>
    <li>
        <Link to='/home'</li> <li> <Link to='/news'</Link> </li> <li> <Link to='/about'> About us </Link> </li> </ul>Copy the code
  1. We create a news.js class for News management, where we distribute the secondary route. We have a News list (route/News /list, component NewsList), and an add News (route/News /add, component NewsAdd). Click Add News and news list to jump to the corresponding route. This feature is supported by the previous implementation without rewriting our own HashRouter, etc

  2. In params Express, there are paths like ‘/news/datail/:id’ in VUE. The following ID is dynamically matched, that is, the path parameter. Similarly, these implementations use the path-to-regXP library. Here we also focus on using this library to implement the function of path parameters. Add a route to news.js to jump to the NewsDetail detail page.

 <Route path='/news/datail/:id' component={NewsDetail}></Route>
Copy the code

Add constructor to route. js to get the regular matching path information by path-to-regexp, and modify the path matching method in render as follows:

constructor(props) {
    super(props);
    let { path } = props;
    this.keys = [];
    this.regxp = pathToRegexp(path, this.keys, { end: false });
    this.keys = this.keys.map(key => key.name);
}
let { location } = this.context;
let result = location.pathname.match(this.regxp);
let props = {
    location,
    history: this.context.history
}
if (result) {
    let [url, ...values] = result;
    props.match = {
        url,
        path,
        params: this.keys.reduce((memo, key, idx) => {
            memo[key] = values[idx];
            returnmemo; }}, {})return<Component {... props}></Component> }else {
    return null;
}
Copy the code

The above props. Match is an important one, as shown in Figure 1 of the infographic for getting the match

  1. The Switch component sometimes mistakenly writes two routes when we write routing information, for example
<Route path='/home' component={Home}></Route>
<Route path='/home' component={Home}></Route>
<Route path='/news' component={News}></Route>
<Route path='/about' component={About}></Route>
Copy the code

If there are two /home, then the page will be displayed twice. In this case, we need a Switch component, covering the outermost layer, so the principle is to match in sequence, and then return directly, no further matching. The logic of switch.js is as follows:

 <Switch>
    <Route path='/home' component={Home}></Route>
    <Route path='/home' component={Home}></Route>
    <Route path='/news' component={News}></Route>
    <Route path='/about' component={About}></Route>
</Switch>
export default class Switch extends Component {
    static contextTypes = {
        location: ProTypes.object
    }
    render() {
        let { pathname } = this.context.location;
        let children = this.props.children;
        for (let i = 0; i < children.length; i++) {
            let child = children[i];
            let { path } = child.props;
            if (pathToRegexp(path, [], { end: false }).test(pathname)) {
                returnchild; }}returnnull; }}Copy the code

summary

To be continued…