What you need to know about the implementation principle of React Router(hash mode)

Single page apps you should know

What is a single page application?

single page web application (SPA) is an application with only one Web page. A Web application that loads only a single HTML page and dynamically updates that page when the user interacts with the application. React and Vue are the main front-end frameworks for building single page applications.

Comparison between single page application and multi page application

contrast Single page application Multi page application
form One shell page and multiple page components (fragments) Multiple complete pages
Resources (css,js) Can be shared, only need to load in the shell part Request from the server when necessary, resource independent
First load Slow loading of the first screen Little difference in each load
User experience Good user experience, content change does not need to reload the entire page, and subsequent server pressure is small Page loading is slow, each load needs to request the server
Transition animation Can be realized Not possible
Search engine optimization (SEO) Poor effect, rendering through SSR server, high cost Good effect

Principle of SPA single page application (role of routing)

By monitoring the changes of the route, the components corresponding to the route are matched and mapped to the route. The framework can effectively update and render components correctly when routing changes.

The implementation process of HashRouter you need to understand

Here I will introduce the implementation principle and process of HashRouter

Three components of routing

There are three types of components in React Router:

  1. Router (including HashRouter and BrowserRouter)

Two modes of corresponding route: hash and history

  1. route matching component (Route)

Display components corresponding to control path

  1. navigation component (Link)

Route switching

Manual implementation process

Take a demo for example

export default class App extends Component {
  render() {
    return (
      <HashRouter>
        <Route path="/home" component={Home}></Route>
        <Route path="/user" component={User}></Route>
      </HashRouter>
    )
  }
}
ReactDOM.render(<App />,
  document.getElementById('root')
);
Copy code

Here, the Route component obtains the corresponding path and the component to be displayed, and is nested in the Router component.

HashRouter components

First of all, we need to know some characteristics of BOM

BOM is a set of API for operating browser, while window is a top-level object in BOM. We can use this.props Print some information attached to windows, take nuggets for example

The implementation of HashRouter depends on these APIs. We can window.location.href Get our url value.

Of course, is that ok? Wait, how does Route, as a nested component of HashRouter, get the url path to match the path?

Here, react router uses the API proposed by react 16.3 React.createContext

Context provides a way to transfer data through component tree

It can solve the problem that the parent component transfers values to the child component, grandchildren, etc., and provide a solution for multi-component nested data transfer.

//We passed a context.js Method to introduce this api
import React from 'react';
let { Provider, Consumer } = React.createContext()
export { Provider, Consumer }
Copy code

The HashRouter acts as the producer through window.addEventListener('hashChange',callback) listens for changes in the hash value and passes it to its nested components.

The specific code is as follows:

import React, { Component } from 'react';
import { Provider } from './context'
// Api under this component is provided to the sub components for use
class HashRouter extends Component {
  constructor() {
    super()
    this.state = {
      location: {
        pathname: window.location.hash.slice(1) || '/'
      }
    }
  }
  // url path change location
  componentDidMount() {
    window.location.hash = window.location.hash || '/'
    window.addEventListener('hashchange', () => {
      this.setState({
        location: {
          ...this.state.location,
          pathname: window.location.hash.slice(1) || '/'
        }
      }, () => console.log(this.state.location))
    })
  }
  render() {
    let value = {
      location: this.state.location
    }
    return (
      <Provider value={value}>
        {
          this.props.children
        }
      </Provider>
    );
  }
}

export default HashRouter;
Copy code

Route component

The Route component acts as the role of the consumer, receives the url path value passed by the HashRouter through a callback, and performs the subsequent matching rendering component

import React, { Component } from 'react';
import { Consumer } from './context'
const { pathToRegexp } = require("path-to-regexp");
class Route extends Component {
  render() {
    return (
      <Consumer>
        {
          state => {
            console.log(state)
            let {path, component: Component} = this.props
            let pathname = state.location.pathname
            let reg = pathToRegexp(path, [], {end: false})
            // Determine whether the current path contains pathname
            if(pathname.match(reg)) {
              return <Component></Component>
            }
            return null
          }
        }
      </Consumer>
    );
  }
}
export default Route;
Copy code

Due to the complexity of the official regular expressions, I use the path to regexp plug-in to handle regular matching.

Effect:

summary

This time, I simply simulated the implementation process of the HashRouter, and I also had some understanding of the implementation principle of react router. Finally, the learning process focuses on summary and sharing. You can see my specific code github Welcome to leave a message and share with me 😀.

Tags: React shell Vue Windows

Posted on Sat, 30 May 2020 17:41:20 -0700 by djKale