What is routing

The word routing is usually heard in network engineering. The concept of front-end engineering and back-end routing refers to the jump of the page, and the browser detects the change of the route and displays the corresponding page on the page. In the early days, the concept of routing was the process of rerendering page layout and content based on URL changes, and this process was implemented on the server side. What he describes is the mapping between urls and functions.In single-page web applications, routing describes the mapping between URL and UI. The salient feature of this mapping relationship isA URL change does not cause a page refresh.六四屠杀

There are two routing modes

The purpose of URL changes is to update the UI, while the page cannot be refreshed. To update the page view UI, we need to listen for URL changes. So implementing a routing engine on the front end requires two things

  1. URL changes don’t swipe the page,
  2. How do I listen for URL changes

There are two routes in the front-end domain that can implement this standard

Hash routing

Hash routing is what we call an anchor point. Add # to the URL, followed by the hash route section. You can listen for changes to hash routes by listening for events

window.addEventListener("hashchange".function(){
	console.log("Route change")})window.onhashchange = function(){
	console.log("Route change")}Copy the code

The history of routing

How do YOU listen for changes to the history route

window.addEventListener('popstate'.function(){
	console.log("Route change")})Copy the code

React-Router

In this column we are only talking about the source code, which corresponds to version 5.2 History: the responsible browser page, where a link change informs the current page that the Location object has changed, and the developer renders the content accordingly. Router: monitors the changes of the page object and starts rendering the page again. Route: After rendering the page, displays the content corresponding to the specific routing address based on the location information of the page.

BrowserRouter and Router

The react-router is used in the following ways:

import { createBrowserHistory } from 'history'
import { Router } from 'react-router'

const BrowserRouter = React.cloneElement(Router, { history: createBrowserHistory() })

export default() = > (<BrowserRouter>.</BrowserRouter>
)
/ / or

export default() = > (<Router history={createBrowserHistory()}>.</Router>
)
Copy the code

After React-Router V4 you can directly use BrowserRouter as shown below

import { BrowserRouter } from 'react-router-dom'

export default() = > (<BrowserRouter>.</BrowserRouter>
)
Copy the code

BrowserRouter is an encapsulation of the Router component, passing in the history attribute. The main part is the source code for the Router

// packages/react-router-dom/modules/BrowserRouter.js

class BrowserRouter extends React.Component {
  history = createHistory(this.props);

  render() {
    return <Router history={this.history} children={this.props.children} />; }}Copy the code
// packages/react-router/modules/Router.js
class Router extends React.Component {
  static computeRootMatch(pathname) {
    return { path: "/".url: "/".params: {}, isExact: pathname === "/" };
  }

  constructor(props) {
    super(props);

    this.state = {
      // BrowserRouter passes history
      location: props.history.location
    };

    if(! props.staticContext) {// Listen for URL changes
      this.unlisten = props.history.listen(location= > {
        // This does not affect the overall logic}); }}// Use the context to pass information such as the history location to children
  render() {
    return (
      <RouterContext.Provider
        value={{
          history: this.props.history.location: this.state.location.match: Router.computeRootMatch(this.state.location.pathname),
          staticContext: this.props.staticContext
        }}
      >
        <HistoryContext.Provider
          children={this.props.children || null}
          value={this.props.history}
        />
      </RouterContext.Provider>); }}Copy the code

The Router does not handle a lot of things. Define a context to pass relevant information to children; 2. Listen for URL changes to change the current state.

Route

The source code for Route is also simple, matching the page to display based on incoming information, as shown below

// packages/react-router/modules/Route.js
class Route extends React.Component {
  // The Consumer context, which takes over the information passed in above
  render() {
    return( <RouterContext.Consumer> {context => { invariant(context, "You should not use <Route> outside a <Router>"); / / the location information If the users to use the incoming information, otherwise, use the Provider to const location = this. Props. The location | | context. The location; // Match: {path,url,isExact,params} const match = this.props.computedMatch? this.props.computedMatch // <Switch> already computed the match for us : this.props.path ? matchPath(location.pathname, this.props) : context.match; // Some judgment is skipped here... let { children, component, render } = this.props; // Start rendering children, <Route exact path="/" Component ={Home} /> // 2. <Route exact path="/" render={props=>{return <Home />}}  /> // 3. <Route exact path="/"><Home /> </Route> return ( <RouterContext.Provider value={props}> {props.match ? children ? typeof children === "function" ? children(props) : children : component ? React.createElement(component, props) : render ? render(props) : null : typeof children === "function" ? children(props) : null} </RouterContext.Provider> ); }} </RouterContext.Consumer> ); }}Copy the code

**Route is used to render components, matching the content to be rendered according to the matching URL (path property of Route). There are three ways to render Component children. It’s a long one, and it’s not that hard to understand. First check whether chidren is a function, and then check whether chidren is a function. This is the logic for rendering children. If there is no children, check whether there is a Component, and finally check whether there is a render method.

Switch

If the Route component is wrapped with a Switch, the matched URL returns the first matched element of the wrapped Route. The core code is as follows:

// packages/react-router/modules/Switch.js
React.Children.forEach(this.props.children, child= > {
  if (match == null && React.isValidElement(child)) {
    element = child;

    const path = child.props.path || child.props.from;

    match = path
      ? matchPath(location.pathname, { ...child.props, path })
    : context.match;
  }
});

return match
  ? React.cloneElement(element, { location, computedMatch: match })
: null;
Copy the code

**Switch does not have much content in it, just traverses the Route of the package and returns the first matched content

Conclusion:

In general, the source code for the React-Router is not difficult to understand. It is a simple judgment. In contrast to this article, there is no introduction to how to use the React-Router, just a brief interpretation of the source code. The next article will implement a simple version of the React – Router. Implement the APIS described earlier.