React路由

1. 什么是SPA单页面应用

  1. 单页Web应用(single page web application,SPA)。
  2. 整个应用只有一个完整的页面。
  3. 点击页面中的链接不会刷新页面,只会做页面的局部更新。
  4. 数据都需要通过ajax请求获取, 并在前端异步展现。

单页面得特点:只需要加载一次主页面,通过局部刷新,就可以实现跳转或者切换页面

优点:加载速度快,用户体验比较好

缺点:

- 第一次加载比传统要慢一点
- 不利seo
- 页面相对复杂
- 返回键

2.什么是路由

简单的说就是根据不同的地址,web服务器处理不同的业务以及逻辑,或者说是根据不同的URL切换组件,实现页面的跳转。

3.路由分类

  1. 后端路由: 根据用户的请求返回不同内容
  2. 前端路由: 根据不同的URL去切换组件

4. react-router-dom

1.它是react的一个插件库

2.专门用来实现一个SPA应用.

3.基于react的项目基本都会用到此库.

5. 路径的基本使用

1.明确好页面中的导航区,展示区

2.导航区的a标签改为link标签,href换成to

3.展示区写Route标签进行路径的匹配

4.<App>的最外侧包裹一个<BrowserRouter>

案例:点击不同标签,显示对应的组件

文件结构:

pages文件夹里面放的是路由组件,和咱们的普通组件一样,只是通过咱们路径渲染出来的组件我们成他为路由组件

components文件里面放的是一般组件,也就是以前的普通组件

5.1 react-router-dom安装

因为脚手架里面并没有帮咱们下载router路由,所以需要咱们自己安装

在控制台里面输入命令 npm i react-router-dom 安装

 

 

安装完成后,在index.js入口文件引入路由,并且使用<BrowserRouter>标签把App组件包裹住

//引入react核心文件

import React from 'react';

//引入react-dom

import ReactDOM from "react-dom";

// 引入路由

import {BrowserRouterfrom 'react-router-dom';

//引入App组件

import App from './App';

// 渲染App到页面

ReactDOM.render(

    //使用路由需要用BrowserRouter标签包住

    <BrowserRouter>

        <App />

    </BrowserRouter>,

    document.getElementById('root')

)

Home组件代码

import React, { Component } from 'react'

export default class Home extends Component {

    render() {

        return (

            <div>

                <h1>我是home页面</h1>

            </div>

        )

    }

}

About组件代码

import React, { Component } from 'react'

export default class About extends Component {

    render() {

        return (

            <h3>我是About的内容</h3>

        )

    }

}

App.js 组件代码

import React, { Component } from 'react'

import {Link,Routefrom "react-router-dom"

//引入pages目录下Home和About路由组件

import Home from "./pages/Home/"

import About from "./pages/About/"

//引入component下header普通组件

import Header from "./components/header/"

export default class App extends Component {

    render() {

        return (

            <div>

                {/* 普通组件使用方法,以标签形式渲染的 */}

                <Header/>

                {/* 注意大小写问题 */}

                {/* 点击不同的link显示对应route里面的组件 */}

                    <Link to='/home'>Home</Link>

                    <br/>

                    <Link to='/about'>About</Link>

                <div>

                    {/* 

                        路由组件使用方法

                        放到Route标签内

                        组件显示区,path是路由的路径,component是要显示对应的组件 

                    */}

                    <Route path='/about' component={About}/>

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

                </div>  

            </div>

        )

    }

}

5.2 路由组件和一般组件

1.写法不同:

一般组件: <Header/>

路由组件: <Route path=”/home” component={Home}>

2.存放位置不同:

一般组件: components

路由组件: pages

  1. 接收到的props不同:

一般组件:写组件标签时传递了什么就能接收到什么内容

路由组件:接收到三个固定的属性

路由组件和一般组件的最大区别是,路由组件当被渲染时props可以自动接收到history,location,match,staticContext属性

路由组件里的代码

import React, { Component } from 'react'

export default class About extends Component {

    render() {

        console.log("我是路由组件",this.props)

        return (

            <h3>我是About的内容</h3>

        )

    }

}

一般组件里面的代码

import React, { Component } from 'react'

export default class Header extends Component {

    render() {

        console.log("我是一般组件",this.props)

        return (

            <h3>我是页头</h3>

        )

    }

}

浏览器调试:

 

5.3 NavLink和Link

根据上面的代码可以看出,link标签里面是用来写导航区的链接,如果想让咱们的链接点击谁,谁有高亮效果,我们需要使用NavLink标签,同时引入react-router-dom的时候要先引入进来

import {Link,NavLink,Routefrom "react-router-dom"

使用的时候

<NavLink to='/about' activeClassName='abc'>About</NavLink>

可以通过activeClassName属性来设置,这个链接点击时添加什么class属性

 

5.4 Switch组件

当注册多个理由路径时,并且路径重复了,为了只展示第一个相同路径的组件其它相同的组件不被渲染可以使用Switch包裹起来

第一步:先要引入这个组件

import {Link,NavLink,Route,Switchfrom "react-router-dom"

第二步:使用<Switch></Switch>把路由导航包裹起来

                    <Switch>

                        <Route path='/about' component={About}/>

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

                        <Route path='/home' component={Admin}/>

                        {/*上面两个path路径相同,但是要渲染的组件不同

                            如果不使用switch组件包裹,这两个组件都会被渲染

                            使用Switch包裹后,之后渲染第一个Home组件

                        */}

                    </Switch>

5.5 解决样式丢失问题

当路由path路径是多级的时候,在刷新时可能会造成样式丢失

                    <Link to='/abc/home'>Home</Link>

                    <NavLink to='/abc/about' activeClassName='abc'>About</NavLink>

解决方法:

第一种:引入样式的时候在路径上加上%PUBLIC_URL%这个,会自动定位到项目的public目录下(常用)

<link rel="stylesheet" href="%PUBLIC_URL%/index.css"/>

第二种:引入样式是把./index.css前面的点去掉(常用)

<link rel="stylesheet" href="/index.css"/>

第三种:使用HashRouter路由模式(很少使用这种)

import {HashRouterfrom 'react-router-dom';

//引入App组件

import App from './App';

// 渲染App到页面

ReactDOM.render(

    <HashRouter>

    <App />

    </HashRouter>,

    document.getElementById('root')

)

5.7 路由的模糊匹配和严格匹配

exact={true}属性

import React, { Component } from 'react'

import {Link,NavLink,Route,Switchfrom "react-router-dom"

//引入pages目录下Home和About路由组件

import Home from "./pages/Home/"

import About from "./pages/About/"

//引入component下header普通组件

import Header from "./components/header/"

export default class App extends Component {

    render() {

        return (

            <div>

                <Header/>

                    <Link to='/home/a/b'>Home</Link>

                    <br/>

                    <NavLink to='/about/a/b' activeClassName='abc'>About</NavLink>

                <div>

                    <Switch>

                        <Route path='/about' component={About}/>

                        <Route exact={true} path='/home' component={Home}/> 

                        {/* 当Route里面加上exact={true}的时候就变成严格匹配

                            上面link里to后面的路径要和path里面的完全一样才能匹配到

                            如果不加这个属性,当link里面的路径开头的路径和path里面能匹配上

                            就能使用,此时上面的代码about就可以使用,但是Home就不能使用

                        */}

                    </Switch>

                    

                </div>  

            </div>

        )

    }

}

  1. 默认使用的是模糊匹配(输入的路径必须包含要匹配的路径,且顺序要一致)
  2. 开启严格匹配:<Route exact={true} path=”/home” component={Home}>
  3. 严格匹配不要随便开启,需要在开,有些时候开启会导致无法继续匹配二级路由

6 Redirect重定向

当你的url路径上什么也不输入,一开始的时候想默认渲染一个组件,可以使用它.

或者当所有路由都无法匹配时,跳转到Redirect指定的路由,一般写在所有路由注册的最下方

使用方法:

第一步:先引入import {Link,Route,Redirectfrom "react-router-dom"

第二步:<Redirect to='/home'/>

to后面是你想要渲染的路由

案例代码:

import React, { Component } from 'react'

import {Link,Route,Redirectfrom "react-router-dom"

//引入pages目录下Home和About路由组件

import Home from "./pages/Home/"

import About from "./pages/About/"

//引入component下header普通组件

import Header from "./components/header/"

export default class App extends Component {

    render() {

        return (

            <div>

                <Header/>

                    <Link to='/home'>Home</Link>

                    <Link to='/about'>About</Link>

                <div>

                        <Route path='/about' component={About}/>

                        <Route exact={true} path='/home' component={Home}/> 

                        {/* 重定向通常写在最后 */}

                        <Redirect to='/home'/> 

                </div>  

            </div>

        )

    }

}

7嵌套路由

当通过路由渲染出来的组件里面还有二级路由或者更多级别的子路由时,需要加上父组件的路径

 

import React, { Component } from 'react'

import Users from './Users/'

import Goods from "./Goods/"

import {NavLink,Route,Switchfrom "react-router-dom"

export default class Home extends Component {

    render() {

        return (

            <div>

                <h1>我是home页面</h1>

                <div>

                    {/* 这里面是home组件下的子路由路径,

                    /home是一级路由地址,后面接一个二级路由地址 */}

                    <NavLink to="/home/users">Users</NavLink>

                      

                    <NavLink to="/home/goods">Goods</NavLink>

                </div>

                <div>

                    <Switch>

                        <Route path='/home/users' component={Users} />

                        <Route path='/home/goods' component={Goods} />

                    </Switch>

                </div>

            </div>

        )

    }

}

注意:嵌套路由不要开启严格匹配

8 路由组件传递参数

8.1使用params传参

import React, { Component } from 'react'

import Detail from './Detail'

import {Route,Link,Switchfrom 'react-router-dom'

export default class Users extends Component {

    state ={

        mess:[

            {id:1,name:"张三",age:18,sex:"男"},

            {id:2,name:"王五",age:23,sex:"男"},

            {id:3,name:"李四",age:16,sex:"女"},

        ]

    }

    render() {

        // 解构赋值获取state里面mess的数据

        const {mess= this.state

        return (

            <div>

                {

                    mess.map((item)=>{

                       return(

                        <li key={item.id}>

                            {/* 向路由组件携带params参数 */}

                            <Link to={`/home/users/detail/${item.id}/${item.name}`}>{item.name}</Link>

                        </li>

                       )

                    })

                }

                <Switch>

                    {/* 声明接收params参数 */}

                    <Route path='/home/users/detail/:id/:name' component={Detail}/>

                </Switch>

            </div>

        )

    }

}

时在detail组件里面this.props.match.params里面就能接收到对应内容

  // 接收params参数

        const {id,name} = this.props.match.params

 

8.2 search传参

在接收参数的组件里面需要引入querystring库,querystring.stringify(obj)可以把对象转换成id=18&name=张三,这种urlencoded编码解构,还可以把urlencoded格式的转换回对象querystring.parse(str)

案例:向detail组件携带参数

第一步

{/* 向路由组件传递search参数 */}

<Link to={`/home/users/detail/?id=${item.id}&name=${item.name}`}>{item.name}</Link>

第二步

{/* search无需声明接收,正常注册路由就行 */}

<Route path='/home/users/detail' component={Detail}/>

第三步 detail组件接收

import React, { Component } from 'react'

import querystring from 'querystring'

export default class Detail extends Component {

    render() {

        console.log(this.props)

        //接收search参数

        const {search= this.props.location //接收search里面的参数

         //使用slice把?接去掉,在使用querystring.parse()转换成对象

        const result = querystring.parse(search.slice(1))

        return (

            <div>

                <li>ID:{result.id}</li>

                <li>用户名:{result.name}</li>

            </div>

        )

    }

}

8.3 state参数

to后面使用对象格式, pathname属性后面写路由地址,state属性后面写要携带的参数

{/* 向路由组件传递state参数 */}

<Link to={{pathname:'/home/users/detail',state:{id:item.id,name:item.name}}}>{item.name}</Link>

datail组件接收代码

//接收state参数

        const {id,name= this.props.location.state || {}

        return (

            <div>

                <li>ID:{id}</li>

                <li>用户名:{name}</li>

            </div>

        )

9 push 和 replace 模式

路由默认使用的时是push模式,浏览过的链接会生成历史记录可以前进后退,而在路由导航标签上添加replace属性,就会开启replace模式,在点击此链接不会生成历史记录

{/* 向路由组件传递state参数 */}

<Link  replace to=’/home’>Home</Link>

10 编程试路由

可以使用路由里面的 this.props.history.push 和  this.props.history.replace两个属性实现编程试路由跳转

    pushShow = (id)=>{

        //push跳转+携带params参数

        this.props.history.push(`/home/users/detail/${id}`)

    }

    replaceShow = (id,title)=>{

        //replace跳转+携带search参数

        this.props.history.replace(`/home/users/detail?id=${id}&title=${title}`)

    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值