Web study notes-React (routing)

The content of the notes is reproduced from AcWing's Web Application Course handout, course link: AcWing Web Application Course .

This section describes how to match pages and URLs one-to-one.

1. Web classification

Web pages can be divided into two broad categories:

  • Static page: The data in the page is hard-coded, that is, the entire file is stored on the server. When the user accesses the URL, the server passes the page information to the front end intact.
  • Dynamic page: The data in the page is filled dynamically, that is, the template of the page is stored on the server , and the data is stored in the database. When the user opens the page, the page will be dynamically spliced ​​together. Nowadays, they are generally dynamic pages.
    • Back-end rendering: Data is filled in at the back-end, that is, the splicing operation of template and data is performed on the server side. The client sends the URL to the server, and the server returns the spliced ​​page.
    • Front-end rendering: Data is filled in at the front-end, that is, the splicing operation of template and data is performed in the user's browser. When the page is opened for the first time , the client sends the URL to the server, and the server returns the templates of all pages . During rendering, it requests data from the server based on what data is currently needed; when the page is opened for the second time, JS is used to directly refresh the current page. page, does not necessarily send a request to the backend.

2.Route component

The Route component allows our front-end page to uniquely correspond to a URL, making the front-end rendering mode look the same as the back-end rendering mode.

We create a new project route-appand open the project with VS Code:

create-react-app route-app

Configure the environment:

  • VS Code installation plug-in:Auto Import - ES6, TS, JSX, TSX
  • Install the Route component (install it in the project root directory, restart VS Code after installation):npm i react-router-dom
  • Install Bootstrap:npm i bootstrap

Route component introduction:

  • BrowserRouter: All components that require routing must be wrapped in BrowserRoutercomponents;
  • Link: Jump to a link (but no request is sent to the backend), tothe attribute indicates the link to jump to;
  • Routes: Similar to the one in C++ switch, but only matches the first path, that is, looking at each path from front to back Route, judging whether the current link is equal to Routethe link in , if so, rendering Routethe component in , and the subsequent judgment will not continue;
  • Route: Route, paththe attribute represents the path, and elementthe attribute represents the content (component) routed to.

We first create the root component of our project App, the navigation bar NavBar, and the components of multiple sub-pages: Home, Linux, Django, Web, NotFound.

NavBarcode show as below:

import React, {
    
     Component } from 'react';

class NavBar extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <nav className="navbar navbar-expand-lg bg-body-tertiary">
                <div className="container-fluid">
                    <a className="navbar-brand" href="/">讲义</a>
                    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" id="navbarNavAltMarkup">
                        <div className="navbar-nav">
                            <a className="nav-link active" aria-current="page" href="/">Home</a>
                            <a className="nav-link" href="/linux">Linux</a>
                            <a className="nav-link" href="/django">Django</a>
                            <a className="nav-link" href="/web">Web</a>
                        </div>
                    </div>
                </div>
            </nav>
        );
    }
}

export default NavBar;

Appcode show as below:

import React, {
    
     Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import NotFound from './notfound';

class App extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <React.Fragment>
                <NavBar />
            </React.Fragment>
        );
    }
}

export default App;

Home, Linux, Django, Web, NotFoundthe codes are similar, only one is shown:

import React, {
    
     Component } from 'react';

class Home extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <h1>Home</h1>
        );
    }
}

export default Home;

Now we render the page based on the URL. Note that this is still back-end rendering, and the page will be reloaded every time. We modify App:

import React, {
    
     Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import NotFound from './notfound';
import {
    
     Routes, Route } from 'react-router-dom'

class App extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <React.Fragment>
                <NavBar />
                <Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route
                    <Route path='/' element={
    
    <Home />} />  // 如果链接为'/'就跳到Home组件
                    <Route path='/linux' element={
    
    <Linux />} />
                    <Route path='/django' element={
    
    <Django />} />
                    <Route path='/web' element={
    
    <Web />} />
                </Routes>
            </React.Fragment>
        );
    }
}

export default App;

Now we Linkreplace NavBarthe link tag in awith so that it becomes front-end rendering:

import React, {
    
     Component } from 'react';
import {
    
     Link } from 'react-router-dom'

class NavBar extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <nav className="navbar navbar-expand-lg bg-body-tertiary">
                <div className="container-fluid">
                    <Link className="navbar-brand" to="/">讲义</Link>
                    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" id="navbarNavAltMarkup">
                        <div className="navbar-nav">
                            <Link className="nav-link" aria-current="page" to="/">Home</Link>
                            <Link className="nav-link" to="/linux">Linux</Link>
                            <Link className="nav-link" to="/django">Django</Link>
                            <Link className="nav-link" to="/web">Web</Link>
                        </div>
                    </div>
                </div>
            </nav>
        );
    }
}

export default NavBar;

3. Pass parameters in the URL

When the website has a large number of pages, it is certainly impossible for us to write so many Route.

Suppose we now have several Web lecture notes, iiThe routing link of article i/web/content/i is: :

import React, {
    
     Component } from 'react';
import {
    
     Link } from 'react-router-dom'

class Web extends Component {
    
    
    state = {
    
    
        webs: [
            {
    
    id: 1, title: 'HTML基础标签'},
            {
    
    id: 2, title: 'CSS'},
            {
    
    id: 3, title: 'JavaScript'},
            {
    
    id: 4, title: '中期项目-拳皇'},
            {
    
    id: 5, title: 'React'},
        ]
    } 
    render() {
    
    
        return (
            <React.Fragment>
                <h1>Web</h1>
                <hr />
                <div>
                    {
    
    this.state.webs.map(web => (
                        <div key={
    
    web.id}>
                            <Link to={
    
    `/web/content/${
      
      web.id}`}>{
    
    web.id + '.' + web.title}</Link>
                        </div>
                    ))}
                </div>
            </React.Fragment>
        );
    }
}

export default Web;

Let’s first implement the components of the handout content WebContent:

import React, {
    
     Component } from 'react';

class WebContent extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <h1>Web Content</h1>
        );
    }
}

export default WebContent;

Then Appwrite the route in (we can’t write multiple <Route path='/web/content/i' element={<WebContent />} />, but use :xxx):

import React, {
    
     Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import WebContent from './webcontent';
import NotFound from './notfound';
import {
    
     Routes, Route } from 'react-router-dom'

class App extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <React.Fragment>
                <NavBar />
                <div className='container'>
                    <Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route
                        <Route path='/' element={
    
    <Home />} />  // 如果链接为'/'就跳到Home组件
                        <Route path='/linux' element={
    
    <Linux />} />
                        <Route path='/django' element={
    
    <Django />} />
                        <Route path='/web' element={
    
    <Web />} />
                        <Route path='/web/content/:chapter' element={
    
    <WebContent />} />
                    </Routes>
                </div>
            </React.Fragment>
        );
    }
}

export default App;

Now how do we WebContentget :chapterthe parameters in ? Let’s first look at how the function component obtains parameters. You can directly use useParamsthe function to obtain parameters:

import React from 'react';
import {
    
     useParams } from 'react-router-dom';

const WebContent = () => {
    
    
    console.log(useParams())
    return (
        <h1>Web Content - {
    
    useParams().chapter}</h1>
    );
}

export default WebContent;

If it is a class component, you need to first set a layer of function components, and then pass useParamsthe function to yourself as a parameter:

import React, {
    
     Component } from 'react';
import {
    
     useParams } from 'react-router-dom';

class WebContent extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        console.log(this.props.params)
        return (
            <h1>Web Content - {
    
    this.props.params.chapter}</h1>
        );
    }
}

export default (props) => (
    <WebContent
        {
    
    ...props}  // 先把函数组件里面的属性展开
        params={
    
    useParams()}
    />
);

4. Search Params transfer parameters

If the website link format is: /web/content?chapter=3, such a link can also obtain parameters.

Let's first change Webthe link form in :

import React, {
    
     Component } from 'react';
import {
    
     Link } from 'react-router-dom'

class Web extends Component {
    
    
    state = {
    
    
        webs: [
            ...
        ]
    } 
    render() {
    
    
        return (
            <React.Fragment>
                <h1>Web</h1>
                <hr />
                <div>
                    {
    
    this.state.webs.map(web => (
                        <div key={
    
    web.id}>
                            <Link to={
    
    `/web/content?chapter=${
      
      web.id}`}>{
    
    web.id + '.' + web.title}</Link>
                        </div>
                    ))}
                </div>
            </React.Fragment>
        );
    }
}

export default Web;

Then WebContentget the parameters of the link in :

import React, {
    
     Component } from 'react';
import {
    
     useSearchParams } from 'react-router-dom';
import {
    
     Link } from 'react-router-dom'

class WebContent extends Component {
    
    
    state = {
    
    
        searchParams: this.props.params[0],  // 用于获取某一个参数
        setSearchParams: this.props.params[1],  // 用于设置链接里的参数,重新渲染页面
    };
    render() {
    
    
        console.log(this.state.searchParams.get('chapter'))
        return (
            <React.Fragment>
                <h1>Web Content - {
    
    this.state.searchParams.get('chapter')}</h1>
                <hr />
                <div>讲义内容</div>
                <hr />
                <Link to='/web'>返回上一级</Link>
            </React.Fragment>
        );
    }
}

export default (props) => (
    <WebContent
        {
    
    ...props}  // 先把函数组件里面的属性展开
        params={
    
    useSearchParams()}
    />
);

Function components are written as follows:

import React from 'react';
import {
    
     useSearchParams } from 'react-router-dom';
import {
    
     Link } from 'react-router-dom'

const WebContent = () => {
    
    
    let [searchParams, setSearchParams] = useSearchParams();
    console.log(searchParams.get('chapter'));
    return (
        <React.Fragment>
            <h1>Web Content - {
    
    searchParams.get('chapter')}</h1>
            <hr />
            <div>讲义内容</div>
            <hr />
            <Link to='/web'>返回上一级</Link>
        </React.Fragment>
    );
}

export default WebContent;

5. Redirect

When a link that does not exist should be redirected 404 Not Found, we first define this route: <Route path='/404' element={<NotFound />} />.

Using Navigatethe component can redirect, we can use wildcards *to match all the remaining paths and then redirect them to /404the page:

import React, {
    
     Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import WebContent from './webcontent';
import NotFound from './notfound';
import {
    
     Routes, Route, Navigate } from 'react-router-dom'

class App extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <React.Fragment>
                <NavBar />
                <div className='container'>
                    <Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route
                        <Route path='/' element={
    
    <Home />} />  // 如果链接为'/'就跳到Home组件
                        <Route path='/linux' element={
    
    <Linux />} />
                        <Route path='/django' element={
    
    <Django />} />
                        <Route path='/web' element={
    
    <Web />} />
                        <Route path='/web/content' element={
    
    <WebContent />} />
                        <Route path='/404' element={
    
    <NotFound />} />
                        <Route path='*' element={
    
    <Navigate replace to='/404' />} />
                    </Routes>
                </div>
            </React.Fragment>
        );
    }
}

export default App;

6. Nested routing

Assuming Linuxthere are two submodules Homeworkand in the component Terminal, we can Appcreate nested routes in :

import React, {
    
     Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import WebContent from './webcontent';
import NotFound from './notfound';
import {
    
     Routes, Route, Navigate } from 'react-router-dom'

class App extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <React.Fragment>
                <NavBar />
                <div className='container'>
                    <Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route
                        <Route path='/' element={
    
    <Home />} />  // 如果链接为'/'就跳到Home组件
                        <Route path='/linux' element={
    
    <Linux />}>
                            <Route path='homework' element={
    
    <h4>Homework</h4>} />
                            <Route path='terminal' element={
    
    <h4>Terminal</h4>} />
                        </Route>
                        <Route path='/django' element={
    
    <Django />} />
                        <Route path='/web' element={
    
    <Web />} />
                        <Route path='/web/content' element={
    
    <WebContent />} />
                        <Route path='/404' element={
    
    <NotFound />} />
                        <Route path='*' element={
    
    <Navigate replace to='/404' />} />
                    </Routes>
                </div>
            </React.Fragment>
        );
    }
}

export default App;

But now /linux/homeworkwhen the web page is executed, the content of the sub-route will not be rendered. We need to add <Outlet />the component to the parent component to fill in the content of the sub-component:

import React, {
    
     Component } from 'react';
import {
    
     Link, Outlet } from 'react-router-dom'

class Linux extends Component {
    
    
    state = {
    
      } 
    render() {
    
    
        return (
            <React.Fragment>
                <h1>Linux</h1>
                <hr />

                <ul className="nav justify-content-center">
                <li className="nav-item">
                    <Link className="nav-link" to="/linux/homework">Homework</Link>
                </li>
                <li className="nav-item">
                    <Link className="nav-link" to="/linux/terminal">Terminal</Link>
                </li>
                </ul>
                <hr />

                <Outlet />
            </React.Fragment>
        );
    }
}

export default Linux;

Guess you like

Origin blog.csdn.net/m0_51755720/article/details/132788417