React学习(五)----- React路由

1、SPA应用的理解

1、单页Web应用(single page web application,SPA)。

2、整个应用只有一个完整的页面

3、点击页面中的链接 不会刷新 页面,只会做页面的 局部更新。

4、数据都需要通过ajax请求获取, 并在前端异步展现。

2、路由

  • 什么是路由???
    1.一个路由就是一个映射关系(key:value)
    2.key为路径, value可能是function或component
  • 路由的分类
    • 后端路由
      1)理解: value是function, 用来处理客户端提交的请求。
      2)注册路由: router.get(path, function(req, res))
      3)工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
    • 前端路由
      1)浏览器端路由,value是component,用于展示页面内容。
      2)注册路由: <Route path="/test" component={Test}>
      3)工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
  • 路由实现:参考之前写过的文章,地址为:https://www.cnblogs.com/wxh0929/p/15049790.html

3、react-router-dom

  • 插件的安装:目前安装的版本为5.3.0
    cnpm i react-router-dom -S
  • 路由组件与一般组件的区别
    1、写法不同
         一般组件:<Home />
         路由组件:<Route path="/home" component={Home}></Route>
    2、存放位置不同
         一般组件:components
         路由组件:pages
    3、接收到的props不同
         一般组件:组件标签传递了什么,就能收到什么
         路由组件:接收到三个固定的属性
    1. history:
      1. go: ƒ go(n)
      2. goBack: ƒ goBack()
      3. goForward: ƒ goForward()
      4. push: ƒ push(path, state)
      5. replace: ƒ replace(path, state)
    2. location:
      1. pathname: "/about"
      2. search: ""
      3. state: undefined
    3. match:
      1. params: {}
      2. path: "/about"
      3. url: "/about"
  • 基本路由的使用
    • 效果

    • 示例
      • 导航区的a标签改为Link标签,用于编写路由链接
        {/* 原生html中,靠a标签跳转不同的页面 */}
        {/* <a className="list-group-item" href="./about.html">About</a>
            <a className="list-group-item active" href="./home.html">Home</a> */}
        
        {/* 在React中,靠路由链接实现切换组件 ----- 编写路由链接  Router是指路由器*/}
         <Router>
            <Link className="list-group-item" to="/about">About</Link>
            <Link className="list-group-item" to="/home">Home</Link>
         </Router>
      • 展示区写Route标签进行路径的匹配注册路由
        {/* 注册路由 */}
         <Router>
              <Route path="/about" component={About}></Route>
              <Route path="/home" component={Home}></Route>
         </Router>

        现象:点击导航栏时内容无法更新,这是因为一个应用只能使用一个路由器来管理,解决方法是,在入口文件index.js中使用一个路由器管理App组件

        import React from "react";
        
        import ReactDOM from "react-dom";
        
        import { BrowserRouter as Router } from "react-router-dom";
        
        import App from "./App";
        
        ReactDOM.render(
          <Router>
            <App />
          </Router>,
          document.getElementById("root")
        );
         {/* 在React中,靠路由链接实现切换组件 ----- 编写路由链接*/}
              <Link className="list-group-item" to="/about">About</Link>
              <Link className="list-group-item" to="/home">Home</Link>
        
        {/* 注册路由 */}
              <Route path="/about" component={About}></Route>
              <Route path="/home" component={Home}></Route>
      • 当你的路由链接想动态添加class属性实现高亮的时候,使用NavLink
        {/* NavLink用于被选中的时候添加类名,类名默认为 active */}
        <NavLink className="list-group-item" to="/about">About</NavLink>
        <NavLink className="list-group-item" to="/home">Home</NavLink>
        
         {/* 更改路由选中后的类名,由于使用的是bootstrap的样式,会出现闪烁现象,因此设置样式需给最高权重 */}
        <NavLink activeClassName="side_link" className="list-group-item" to="/about">About</NavLink>
        <NavLink activeClassName="side_link" className="list-group-item" to="/home">Home</NavLink>
        
        {/* 设置路由选中的行间样式 */}
        <NavLink activeStyle={{backgroundColor:'orange'}} className="list-group-item" to="/about">About</NavLink>
        <NavLink activeStyle={{backgroundColor:'orange'}} className="list-group-item" to="/home">Home</NavLink>
        • NavLink的封装
          import React, { Component } from 'react'
          import {NavLink} from 'react-router-dom'
          
          export default class MyNavLink extends Component {
            // 标签体内容是一个特殊的标签属性,通过this.props.children可以获取标签体内容
            render() {
              return (
                <NavLink activeClassName="side_link" className="list-group-item" {...this.props} />
              )
            }
          }

          例子:

          <MyNavLink to="/about">About</MyNavLink>

    • Switch的使用
      • 通常情况下,path和component是一一对应的关系,但是当一个path匹配多个component时,多个组件都会同时展示,例如
        <Route path="/home" component={About}></Route>
        <Route path="/home" component={Home}></Route>

        现象:

         解决方法:Switch组件包裹你注册的所有路由,那么只会匹配一个路由的组件,不会继续向后匹配(Switch可以提高路由匹配效率,即单一匹配

        <Switch>
            <Route path="/home" component={About}></Route>
            <Route path="/home" component={Home}></Route>
        </Switch>
    • 路由的模糊匹配与严格匹配
      // 默认使用的是模糊匹配,(简单记:【输入的路径to】必须包含要【匹配的路径path】
      // 且【顺序要一致】,如果to="a/home/b" path="/home",则无法匹配,to="/home/a/b" path="/home" ,则可以匹配)
      <MyNavLink to="/home/a/b">Home</MyNavLink>
      <Route path="/home" component={Home}></Route>
      
      // 解决:开启严格匹配,但是严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
      <Route exact path="/home" component={Home}></Route>
    • 路由的重定向

                    

  •  嵌套路由(二级路由)的使用
    • 注意:
      1、注册子路由时要写上父路由的path值;
      2、路由的匹配是按照注册路由的顺序进行的;
    • 路由组件传递参数
      • 第一种方式:params(http://localhost:3000/home/message/detail/003/%E6%B6%88%E6%81%AF3)   注意:必须要传,否则进不去
        1、路由链接(携带参数)
        {/* 向路由组件传递params参数 */}
        <Link to={`/home/message/detail/${el.id}/${el.title}`}>{el.title}</Link>
        
        2、注册路由(声明接收)
        <Route path="/home/message/detail/:id/:title" component={Detail}></Route>
        
        3、接收参数
        let { id, title } = this.props.match.params;
      • 第二种方式:search/query(http://localhost:3000/home/message/detail/?id=002&title=%E6%B6%88%E6%81%AF2)注意:不传值也可以进去
        1、路由链接(携带参数)
        {/* 向路由组件传递search参数 */}
        <Link to={`/home/message/detail/?id=${el.id}&title=${el.title}`}>{el.title}</Link>
        
        2、注册路由(search参数无需声明接收,正常注册路由即可)
        <Route path="/home/message/detail" component={Detail}></Route>
        
        3、接收参数
        import qs from 'querystring' //无需安装,react内置
        //备注;获取到的search是urlencoded编码字符串,使用qs进行解析,它的parse方法能解析key=value&key=value的字符串
        let {id,title} = qs.parse(this.props.location.search.slice("1"))
      • 第三种方式:state(http://localhost:3000/home/message/detail)
        1、路由链接(携带参数)
        {/* 向路由组件传递state参数 */}
        <Link to={{pathname:'/home/message/detail',state:{id:el.id,title:el.title}}}>{el.title}</Link>
        
        2、注册路由(state参数无需声明接收,正常注册路由即可)
        <Route path="/home/message/detail" component={Detail}></Route>
        
        3、接收参数
        // 备注:页面刷新后,数据不会丢失,因为BrowserRouter会对history对象进行保存,而location是history的一个参数
        // 而HashRouter刷新后会导致路由state参数的丢失
        let { id, title } = this.props.location.state || {};
  • push与replace模式的区别???
    1、react中的路由跳转默认使用的是push模式,即压栈的形式,会留下痕迹;
    2、replace模式则是替换模式,即类似于无痕浏览;
  • 编程式路由导航:借助this.props.history对象上的API来实现路由的跳转、前进与后退等;
    • 使用场景:点击登录按钮登陆成功后,自动跳转到应用的首页,通过JS代码来实现路由跳转;
    • 跳转方式
      • push跳转
        // 1、携带params参数
        this.props.history.push(`/home/message/detail/${el.id}/${el.title}`)
        
        // 2、携带search参数
        this.props.history.push(`/home/message/detail/?id=${el.id}&title=${el.title}`)
        
        // 3、携带state参数
        this.props.history.push(`/home/message/detail/`,{id:el.id,title:el.title})
      • replace跳转
        // 1、携带params参数
        this.props.history.replace(`/home/message/detail/${el.id}/${el.title}`)
        
        // 2、携带search参数
        this.props.history.replace(`/home/message/detail/?id=${el.id}&title=${el.title}`)
        
        // 3、携带state参数
        this.props.history.replace(`/home/message/detail/`,{id:el.id,title:el.title})
      • go跳转
        // 正数代表前进几步、负数代表后退几步,0代表刷新
        this.props.history.go(2)
      • 前进
        this.props.history.goForward()
      • 后退
        this.props.history.goBack()
      •  如何让一般组件也可以使用编程式路由导航???
        import {withRouter} from 'react-router-dom'
        
        class Header extends React.Component{}
        
        // withRouter可以加工一般组件,让一般组件具备路由组件特有的API,他的返回值是一个新组件
        export default withRouter(Header)

4、遇到的问题

  • 解决多级路径刷新页面样式丢失的问题
    1、public/index.html中,引入样式 不写 ./  写 / (常用)
    2、public/index.html中,引入样式 不写 ./  写 %PUBLIC_URL%(常用)
    3、使用HashRouter
posted @ 2021-09-14 14:05  北栀女孩儿  阅读(219)  评论(0编辑  收藏  举报