← 返回首页
React基础教程(十六)
发表时间:2022-06-30 23:10:51
react-router

React-Router作为React体系的一个重要部分,是一个路由库。其可管理URL,实现组件的切换和状态的变换。

1.单页面应用

单页面得特点:只需要加载一次主页面,通过局部刷新,就可以实现跳转或者切换页面。 优点:加载速度快,用户体验比较好。 缺点: - 第一次加载比传统要慢一点 - 不利seo - 页面相对复杂 - 返回键

2.HashRouter和BrowserRouter

HashRouter:在路径中包含了#,相当于HTML的锚点定位。(# 符号的英文叫hash,所以叫HashRouter) 。HashRouter不能(除非手动拼接URL字符串),因此一般配合Redux使用,实现组件间的数据通信。

BrowserRouter:使用的是HTML5的新特性History,没有HashRouter(锚点定位)那样通用,低版本浏览器可能不支持。BrowserRouter进行组件跳转时可以传递任意参数实现组件间的通信。

注意:当使用HashRouter把APP根组件的元素包裹起来之后,网站就已经启用路由了,在一个HashRouter中,只能有唯一的一个根元素。 在一个网站中,只需要使用唯一的一次就行了。

3.Route和Link

Route: Route表示一个路由规则,在Route上,有两个比较重要的属性,path,component。Route创建的标签,就是路由规则,其中path表示要匹配的路由,component表示要展示的组件。Route具有两种身份:1.它是一个路由匹配规则;2.它是一个占位符,表示将来匹配到的组件都放到这个位置

Link: Link表示一个路由的链接,属性to,to属性的地址也是/开头,Link在页面渲染的是a标签。

注意: - Route 组件path地址是以/开头 ,配置component属性,是显示的组件,这个属性不可以大写。 - Route组件可以单双标签使用,单标签需要/结尾,双标签不可以在中间写入别的东西。

4.路由传值

通过配置路由的地址,在Link跳转时: - Route path路径后面 /:id (key) - Link to 路径后面 /top/10 (value)

接收传值: - class类组件,this.props.match.params.属性名 - 函数组件:形参.match.params.属性名

5.嵌套路由

嵌套路由:在路由组件中,使用Link, Route,配置子路由,实现跳转,切换;下面为一级路由,在一级路由Home为路由组件。

<Route path="/home" component={ Home }></Route>

在Home组件中继续使用Link,Route进行路由的嵌套,需要注意的就是路由地址,前部分为一级路由地址,后面接一个二级路由相应的路径。

render() {
    return (
        <div>
            <ul>
                <li><Link to="/home/a">推荐</Link></li>
                <li><Link to="/home/b">新时代</Link></li>
                <li><Link to="/home/c">动漫</Link></li>
            </ul>
            <Route path="/home/a" component={ A }></Route>
            <Route path="/home/b" component={ B }></Route>
            <Route path="/home/c" component={ C }></Route>
        </div>
    )
}

6.NavLink

NavLink带有选中activeClassName ,如果路由处于激活状态,显示激活class样式。NavLink增加了一个activeClassName属性绑定一个class类样式,这时在触发NavLink时,会触发相应得样式,这样有一个切换效果。

7.重定向

Redirect 重定向 具备to属性,可以直接跳转到指定路由。在render方法中,使用内置组件,Redirect内置组件使用to属性,当执行到内置标签时,会进行to跳转路由,to后面接的地址是什么,就可以匹配到相应得路由组件。例如:

<Redirect to="/home/c"></Redirect>

8.Switch

Switch 具有排他性,在组件中使用Switch标签包裹所有得Route,这时,Route相当于每一个path都是精准的匹配,展示相应的组件,最后一个Route是一个不具备地址的路由路径,如果当Link指向一个不存在的地址时,没有精准的匹配到地址,那么会显示到C404路由,使用Switch只会显示一个组件,匹配到为止。

<Switch>
    <Route path="/home" component={ Home }></Route>
    <Route path="/video" component={ Video}></Route>
    <Route path="/book" component={ Book }></Route>
    <Route path="/news" component={ News }></Route>
    <Route path="/user" component={ User }></Route>
    <Route component={ C404 }></Route>
</Switch>

综合案例

项目结构图如下:

package.json 依赖如下:

"devDependencies": {
    "@babel/core": "^7.18.5",
    "@babel/plugin-transform-runtime": "^7.18.5",
    "@babel/preset-env": "^7.18.2",
    "@babel/preset-react": "^7.17.12",
    "babel-loader": "^8.2.5",
    "css-loader": "^6.7.1",
    "css-minimizer-webpack-plugin": "^4.0.0",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.6.1",
    "sass": "^1.52.3",
    "sass-loader": "^13.0.0",
    "style-loader": "^3.3.1",
    "terser-webpack-plugin": "^5.3.3",
    "webpack": "^5.73.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.9.2",
    "webpack-merge": "^5.8.0"
  },
  "dependencies": {
    "@babel/runtime": "^7.18.3",
    "axios": "^0.27.2",
    "react": "^16.8.0",
    "react-dom": "^16.8.0",
    "react-router-dom": "^5.2.1"
  }

src/style.css

.red{
    color: lightsalmon;
}

src/About.js

import React, { Component } from 'react'
export default class About extends Component {
    render() {
        return (
            <div>
                关于我们
            </div>
        )
    }
}

src/Goods.js

import React, { Component } from 'react'
export default class Goods extends Component {
    render() {
        console.log(this.props)
        return (
            <div>
                产品中心
            </div>
        )
    }
}

src/Home.js

import React, { Component } from 'react'
export default class Home extends Component {
    render() {
        return (
            <div>
                网站首页
            </div>
        )
    }
}

src/News.js

import React, { Component } from 'react'

export default class News extends Component {
    //代码优化
    constructor(props){
        super();
        this.state = {
            routeParams:props.match.params
        }
    }
    render() {
        //console.log(this.props)
        //let {cid,nid} = this.props.match.params
        return (
            <div>
                {/*新闻中心 -- {cid},{nid}*/}
                新闻中心--{this.state.routeParams.cid},{this.state.routeParams.nid}
            </div>
        )
    }
}

src/Search.js

import React, { Component } from 'react'
export default class Search extends Component {
    render() {
        return (
            <div>
                搜索页面
            </div>
        )
    }
}

src/Main.js

import React, { Component } from 'react'
import { Link, Route, Switch,NavLink } from 'react-router-dom'
import About from './About'
import Goods from './Goods'
import Home from './Home'
import News from './News'
import Search from "./Search";
import "./style.css";

export default class Main extends Component {
    render() {
        return (
            <div>
                <NavLink activeClassName="red" to="/home">首页</NavLink> &nbsp;&nbsp;
                <NavLink activeClassName="red" to="/classify/1/news/12">新闻</NavLink> &nbsp;&nbsp;
                <NavLink activeClassName="red" to="/goods?id=11">产品</NavLink> &nbsp;&nbsp;
                <NavLink activeClassName="red" to="/about">关于</NavLink> &nbsp;&nbsp;
                <NavLink activeClassName="red" to="/search">搜索</NavLink>&nbsp;&nbsp;
                <button onClick={this.goto.bind(this)}>详情</button>

                <hr></hr>

                <Switch>
                    {/* 动态路由 */}
                    <Route path="/classify/:cid/news/:nid" component={News} />
                    <Route path="/goods" component={Goods} />
                    <Route path="/about" component={About} />
                    <Route path="/search" component={Search}/>
                    <Route path="/home" component={Home} />
                </Switch>
            </div>
        )
    }

    goto(){
        // window.location.hash = '/details'
        // this.props.history.push({
        //     pathname: '/details',
        //     state: {
        //         id: 12
        //     }
        // })

        this.props.history.push({
            pathname: '/details',
            news: {
                id: 12,
                title: '新闻标题',
                createTime: '2021-1-1'
            }
        })
    }
}

src/Login.js

import React, { Component } from 'react'
export default class Login extends Component {
    render() {
        return (
            <div>
                登录页面
            </div>
        )
    }
}

src/Details.js

import React, { Component } from 'react'
import { Redirect } from 'react-router'

export default class Details extends Component {

    state = {
        news: {}
    }

    componentWillMount(){
    //    this.state.news = this.props.history.location.news 
    }

    render() {
        console.log(this.props)
        return (
            <div>
                {this.isLogin()}


                {/* <p>{this.state.news.title}</p> */}
                {/* <Redirect to="/login"></Redirect> */}
            </div>
        )
    }

    isLogin(){
        let user 
        if(user){
            return (
                <p>新闻详情</p>
            )
        }else{
            return <Redirect to="/login"></Redirect>
        }
    }

    componentDidMount(){
        // this.state.news = this.props.history.location.news 
    }
}

src/App.js

import React, {Component} from 'react'
import {BrowserRouter, HashRouter, Route, Switch} from 'react-router-dom'
import Details from './Details'
import Login from './Login'
import Main from './Main'

export default class App extends Component {
    render() {
        return (
            <BrowserRouter>
                <Switch>
                    <Route path="/login" component={Login}/>
                    <Route path="/details" component={Details}/>
                    <Route path="/" component={Main}/>
                </Switch>
            </BrowserRouter>
        )
    }
}

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'

ReactDOM.render(<App />,document.getElementById('root'));

运行效果: