React全家桶-03-react中的路由

353 阅读3分钟

1.React路由的基本使用和404not-found

安装(笔者这里使用的是v5.2.0版本的react-router-dom):

yarn add react-router-dom 

代码示例:

//app.js
import React, {Component} from 'react';
import {BrowserRouter as Router,Route,Link,Switch} from "react-router-dom";
import Home from "./pages/Home.js";
import Course from "./pages/Course.js";
import User from "./pages/User.js";
import NotFound from "./pages/NotFound";
import List from "./pages/List";

class App extends Component {
  render() {
    return (
          <Router>
            <ul>
              <li>
                <Link to="/"> 首页 </Link>
              </li>
              <li>
                <Link to="/course"> 课程 </Link>
              </li>
              <li>
                <Link to="/user"> 用户 </Link>
              </li>
                <li>
                    <Link to="/list"> 列表页 </Link>
                </li>
            </ul>
            {/*路由配置*/}
              <Switch>
                {/*🚀①号*/}
                <Route exact path="/" component={Home} />
                <Route  path="/course" component={Course}/>
                <Route  path="/user" component={User}/>
                <Route  path="/list" component={List}/>
                <Route component={NotFound}/>
              </Switch>
          </Router>
    );
  }
}
export default App;

  • Link标签相当于hmtla标签

  • 使用HashRouter标签后,url路径会有#

  • Route添加exact属性后是精确匹配

  • Switch相当于一个开关,不添加Switch的话,无论访问哪个路径,NotFound组件都会被匹配渲染出来

  • 🚀Route如果用的是闭合标签是不能有空格的,因为如果有空格了,会弹出警告并且component中的组件不会被渲染

    // 🚀出现的提示:
    Warning: You should not use <Route component> and <Route children> in the same route; <Route component> will be ignored
    

2.React中嵌套路由配置及例子:

http://localhost:3000/course/react如果是这种形式的url,那么该如何处理呢🤔?

🚀 App中内容不变,所以从Course组件入手:

//Course.js
import React, {Component} from 'react';
import {Route, Link} from "react-router-dom";
import CourseDetail from "./CourseDetail";
import CourseIndex from "./CourseIndex";
class Course extends Component {
    render() {
        return (
            <div>
              {/*🚀 定义二级路由*/}
              <ul>
                  <li>
                      <Link to="/course/react"> React课程</Link>
                  </li>
                  <li>
                      <Link to="/course/vue"> Vue课程</Link>
                  </li>
                  <li>
                      <Link to="/course/angular"> Angular课程</Link>
                  </li>
              </ul>
              {/*🚀 二级路由配置*/}
              <Route exact path="/course/:courseId" component={CourseDetail}/>
              <Route path={this.props.match.path} component={CourseIndex}/>
            </div>
        );
    }
}
export default Course;
  • 如果Route使用component属性的时候,Route标签之间不能有空格
  • path="/course/:courseId"主要说两点:
    • course路径前面的/不能少
    • :courseId是路由要传递的参数,用于传递react、vue、angular三个中的一个
  • this.props.match.path让路由变成了动态的,值为匹配当前组件的path路径,这里就是/course

🚀再来看下CourseDetail组件中的内容

//CouresDetail.js
import React, {Component} from 'react';

class CourseDetail extends Component {
    componentDidMount() {
        console.log("我是课程详情",this.props.match.params.courseId)
    }
    render() {
        const {location,match,history}  = this.props;
        // 🚀 location:本地信息对象
        // 🚀 match:匹配路由信息对象
        // 🚀 history:历史对象
        console.log(location,match,history);
        return (
            <div>
                报名的课程为:{match.params.courseId}
            </div>
        );
    }
}
export default CourseDetail;
  • Router标签包裹后,props会增加3个对象:
    • location:本地信息对象
    • match:匹配路由信息对象
    • history:历史对象
  • 解构上面三个对象之后,可以使用,通过match.params.courseId获取到了Course组件中的couresId(react,vue,angular三个之一)

3.编程式导航的使用

直接上代码,欧哒欧哒欧哒...

//  CourseDetail.js

import React, {Component} from 'react';
class CourseDetail extends Component {
    componentDidMount() {
        console.log("我是课程详情",this.props.history)
    }
    // 这一这里是箭头函数,不然需要constructor中使用bind绑定
    back = ()=>{
         this.props.history.goBack();
    }
    goIndex=()=> {
        // 🚀 编程式路由
        this.props.history.push("/");
    }
    goHome=()=>{
        // 🚀 传入参数的版本
        this.props.history.push({
            pathname:"/",
            state:{
                foo:"bar"
            }
        })
    }
    render() {
        const {match,location,history} = this.props;
        //🚀location:本地信息对象
        //🚀match:匹配路由信息对象
        //🚀history:历史对象
        console.log(location,match,history);
        return (
            <div key={this.props.location.key}>
                报名的课程为:{match.params.courseId}
                <p>
                    <button onClick={this.back}>返回上一级</button>
                    <button onClick={this.goIndex}>跳转至首页</button>
                    <button onClick={this.goHome}>带参数跳转</button>
                </p>
            </div>
        );
    }
}
export default CourseDetail;

然后来看下传递到Home.js中的state

//Home.js

import React, {Component} from 'react';
class Home extends Component {
    componentDidMount() {
        console.log("我进来了,我是location里面的state",this.props.location)
    }
    render() {
        return (
            <div>
                我是HOME页面
                {this.props.location.state ? this.props.location.state.foo:""};
            </div>
        );
    }
}
export default Home;

🚀 结果如下:

4.重定向路由组件的使用:

常用的一般是访问"/""/home"都访问的是Home.js;来看下修改后的代码:

// App.js

import React, {Component} from 'react';
import {BrowserRouter as Router,Route,Link,Switch,Redirect} from "react-router-dom";
import Home from "./pages/Home.js";
import Course from "./pages/Course.js";
import User from "./pages/User.js";
import NotFound from "./pages/NotFound";
import List from "./pages/List";
class App extends Component {
  render() {
    return (
          <Router>
            <ul>
              <li>
                <Link to="/"> 首页 </Link>
              </li>
              <li>
                <Link to="/course"> 课程 </Link>
              </li>
              <li>
                <Link to="/user"> 用户 </Link>
              </li>
                <li>
                    <Link to="/list"> 列表页 </Link>
                </li>
            </ul>
            {/*路由配置*/}
              <Switch>
                {/*🚀 ①号*/}
                <Route exact path="/home" component={Home} />
                <Route  path="/course" component={Course}/>
                <Route  path="/user" component={User}/>
                <Route  path="/list" component={List}/>
                {/* 🚀 这里要放在NotFound前面,因为Switch找到了符合条件的组件,就不往下面继续走了*/}
                <Redirect to="/home"/>
                <Route component={NotFound}/>
              </Switch>
          </Router>
    );
  }
}
export default App;

5.路由的查询参数展示:

类似于http:localhost:3000/user?id=3这种在路由中是如何获取的?id的部分呢?

下面以组件User组件为例,代码如下:

//User.js

import React, {Component} from 'react';
//http:localhost:3000/user?userId=3
import {Link} from "react-router-dom";

function ShowUser({id}){
    return (
        <div>当前用户:{id}</div>
    )
}

class User extends Component {
    render() {
      // 🚀 这个地方用的是URLSearchParams来存查询的key和value键值对
        const params = new URLSearchParams(this.props.location.search);
        console.log(params);
        return (
            <div>
                <ul>
                    <li><Link to={{pathname:'/user',search:"?id=1"}}>用户1</Link></li>
                    <li><Link to={{pathname:'/user',search:"?id=2"}}>用户2</Link></li>
                    <li><Link to={{pathname:'/user',search:"?id=3"}}>用户3</Link></li>
                </ul>
                <ShowUser id={params.get("id")}/>
            </div>
        );
    }
}
export default User;

这里用URLSearchParams来存储查询的参数id,如果涉及多个参数还可以通过for...of进行循环,更多操作还请看下面的地址:

developer.mozilla.org/zh-CN/docs/…