React 路由

React路由分为三类,WEB,NATIVE,ANYWHERE,根据名字就可以知道,第一种主要用于web开发,第二种主要运用于native开发,第三种这哪种情况下都能用,虽然第一种和第三种都能运用于web开发,但第一种更合适。以下内容介绍第一种。 

一,安装react路由

使用路由要先在脚手架里安装。

npm i react-router-dom

react-router-dom是react的一个插件库。

二,路由的使用

react项目是一个单页面项目,其中的内容由组件构成。点击页面中的链接不会刷新页面,只会做页面的局部更新。

1,基础用法

        下面代码的结构:

        在App.js中注册了两个路由,跳转到Teacher组件和Student组件, (基础使用);

        在Student组件中注册了两个路由,跳转到Message组件和Grade组件,(嵌套路由);

        在Grade组件中动态注册路由,跳转到Detail组件中,Detail组件展示数据,(路由传参)。

App.js

import React, { Component } from 'react'
import {Route, NavLink, Switch, Redirect} from 'react-router-dom'
import Teacher from './pages/Teacher'
import Student from './pages/Student'
import Student2 from './pages/Student2'
import './index.css'

export default class App extends Component {
	render() {
		return (
			<div>
				<div>
					<div >
						{/* 在React中靠路由链接实现切换组件--编写路由链接 */}	
						<NavLink activeClassName="highlight" className="btn" to="/teacher">Teacher</NavLink>
						<NavLink activeClassName="highlight" className="btn" to="/student">Student</NavLink>
					</div>
					{/* 注册路由 */}
                    <Switch>
					    <Route path="/teacher" component={Teacher}/>
					    <Route path="/student" component={Student}/>
                        <Route path="/student" component={Student2}/>
					    {/* <Redirect to="/teacher"/> */}
                    </Switch>
				</div>
			</div>
		)
	}
}

Teacher

import React, { Component } from 'react';


export default class Teacher extends Component {
  render() {
    return (
        <div>
          <h3>Teacher</h3>
        </div>
    );
  }
}

分为下面三个步骤:

(1)先要从react-router-dom这个库中引入需要使用的内容。

(2)定义路由,编写路由链接,<NavLink></NavLink>编写,to=""表示路由的路径。

通过activeClassName指定样式名。给它添加了一个高亮的效果。

上面是导航,下面是组件中的内容。 

(3)注册路由,path=""表示路径,component表示需要显示的组件。

<Switch>:通常情况下,path和component是一一对应匹配的,Switch能够单一匹配。

如果有两个组件对应同一个path,不加Switch时,两个组件都会显示。

加上Switch时,只会匹配第一个。

 

 <Redirect />:代表重定向,当所有路由都无法匹配时,跳转到Redirect指定的路由。一般用在页面刚加载时,页面应该显示一个组件。

 (4)最后,要用<BrowserRouter>或<HashRouter>将路由包起来,一个项目中需要路由的地方很多,react脚手架只显示App.js一个组件,所以直接包裹在<App>外侧。

2,嵌套路由

        在Student组件中再添加两个路由,App.js中的内容和上面的一样。

Student组件

import React, { Component } from 'react';
import { NavLink, Route, Switch, Redirect } from 'react-router-dom'
import Message from './Message';
import Grade from './Grade';

export default class Student extends Component {
  
  render() {
    return (
      <div>
        <h3>Student</h3>
        <div>
           <NavLink activeClassName="highlight" className="btn" to="/student/message">Message</NavLink>
           <NavLink activeClassName="highlight" className="btn" to="/student/grade">Grade</NavLink>
            {/* 注册路由 */}
            <Switch>
              <Route path="/student/message" component={Message}/>
              <Route path="/student/grade" component={Grade}/>
              <Redirect to="/student/message" />
            </Switch>
          </div>
      </div>
        
    );
  }
}

Grade组件

import React, { Component } from 'react';

export default class Grade extends Component {
  render() {
    return (
        <div>Grade</div>
    );
  }
}

         注册子路由时要写上父路由的path值。to="/student/message",/student是父路由,/message是子路由。

        路由的匹配是按照注册路由的顺序进行的。

 3,运用路由传递参数

        组件分为一般组件和路由组件;

(1)写法不同:

        一般组件:<Student />

        路由组件:<Route path="/student" component={Student}/>

(2)传递的参数不同:

        一般组件:在组件标签里写什么就会传递什么。

 第一张图片什么都不传,第二张图片传a=1

        路由组件:会接收到三个固定的属性,history,location,match。

withRouter

        给一般组件添加withRouter,一般组件也可以使用路由组件的三个固定属性。

        传递参数有三种方法,携带params参数,携带search参数,携带state参数。

        每种方法都有三个步骤:

(1),路由链接,携带参数

(2),注册路由,声明接收参数

(3),在子组件接收参数

        携带params参数

Grade组件

import React, { Component } from 'react';
import {Link,Route} from 'react-router-dom'
import Detail from './Detail';

export default class Grade extends Component {
  
  state = {
    nameArr: [
      {id:'01', name:'zs'},
      {id:'02', name:'ls'},
      {id:'03', name:'ww'},
    ]
  }
  
  render() {
    const {nameArr} = this.state
    return (
        <div>
          <ul>
            {
              nameArr.map((msgObj)=>{
                return (
                  <li key={msgObj.id}>
                    {/* 携带params参数 ,都能写对象,只写一个路径*/}
                    <Link to={`/student/grade/detail/${msgObj.id}/${msgObj.name}`}>{msgObj.name}</Link>
                  </li>
                )
              })
            }
          </ul>
          <hr />
          {/* 声明接收params */}
          <Route path="/student/grade/detail/:id/:name" component={Detail} />
        </div>
    );
  }
}

Detail组件

import React, { Component } from 'react';

const GradeData = [
    {id: '01', grade:'70'},
    {id: '02', grade:'80'},
    {id: '03', grade:'90'},
]

export default class Detail extends Component {
  

  render() {
    console.log(this.props)

    // 接收params参数
    const {id, name} = this.props.match.params
    

    // 传过来的id和Grade种的数据比较
    const nameGrade = GradeData.find((detailObj)=>{
      return detailObj.id === id
    })

    return (
        <div>
            <div>name:{name}</div>
            <div>grade:{nameGrade.grade}</div>
        </div>
    );
  }
}

 

         这种方法会将参数带到页面的地址栏中。

 (1),携带参数;

<Link to={`/student/grade/detail/${msgObj.id}/${msgObj.name}`}>{msgObj.name}</Link>

(2),声明接收;

<Route path="/student/grade/detail/:id/:name" component={Detail} />

(3),子组件接收参数,要先找到携带的参数在哪儿;

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

        携带search参数

Grade组件

import React, { Component } from 'react';
import {Link,Route} from 'react-router-dom'
import Detail from './Detail';

export default class Grade extends Component {
  
  state = {
    nameArr: [
      {id:'01', name:'zs'},
      {id:'02', name:'ls'},
      {id:'03', name:'ww'},
    ]
  }
  
  render() {
    const {nameArr} = this.state
    return (
        <div>
          <ul>
            {
              nameArr.map((msgObj)=>{
                return (
                  <li key={msgObj.id}>
                    {/* 携带search参数 */}
                    <Link to={`/student/grade/detail?id=${msgObj.id}&name=${msgObj.name}`}>{msgObj.name}</Link>
                  </li>
                )
              })
            }
          </ul>
          <hr />
          {/* search参数无需声明接收 */}
          <Route path="/student/grade/detail" component={Detail} />
        </div>
    );
  }
}

Detail组件

import React, { Component } from 'react';
import qs from 'qs'

const GradeData = [
    {id: '01', grade:'70'},
    {id: '02', grade:'80'},
    {id: '03', grade:'90'},
]

export default class Detail extends Component {
  

  render() {
    console.log(this.props)

    // 接收search参数
    const {search} = this.props.location
    const {id, name} = qs.parse(search.slice(1))

    // 传过来的id和Grade种的数据比较
    const nameGrade = GradeData.find((detailObj)=>{
      return detailObj.id === id
    })

    return (
        <div>
            <div>name:{name}</div>
            <div>grade:{nameGrade.grade}</div>
        </div>
    );
  }
}

        这种方法也会在页面的路径中显示传递的内容。

(1),携带参数;

<Link to={`/student/grade/detail?id=${msgObj.id}&name=${msgObj.name}`}>{msgObj.name}</Link>

(2),声明接收,search不需要声明接收;

<Route path="/student/grade/detail" component={Detail} />

(3),接收参数,接收到的是字符串格式的,需要使用一个第三方库qs进行转化;

 const {id, name} = this.props.location.search

        携带state参数

Grade组件

import React, { Component } from 'react';
import {Link,Route} from 'react-router-dom'
import Detail from './Detail';

export default class Grade extends Component {
  
  state = {
    nameArr: [
      {id:'01', name:'zs'},
      {id:'02', name:'ls'},
      {id:'03', name:'ww'},
    ]
  }
  
  render() {
    const {nameArr} = this.state
    return (
        <div>
          <ul>
            {
              nameArr.map((msgObj)=>{
                return (
                  <li key={msgObj.id}>
                    
                    {/* 携带state参数,这个需要写state,所以只能写对象 */}
                    <Link to={{pathname:'/student/grade/detail', state:{id:msgObj.id, name:msgObj.name}}}>{msgObj.name}</Link>
                  </li>
                )
              })
            }
          </ul>
          <hr />
          {/* state参数无需声明接收 */}
          <Route path="/student/grade/detail" component={Detail} />
        </div>
    );
  }
}

Detail组件

import React, { Component } from 'react';

const GradeData = [
    {id: '01', grade:'70'},
    {id: '02', grade:'80'},
    {id: '03', grade:'90'},
]

export default class Detail extends Component {
  
  render() {
    console.log(this.props)
    
    // 接收state参数
    const {id, name} = this.props.location.state

    // 传过来的id和Grade种的数据比较
    const nameGrade = GradeData.find((detailObj)=>{
      return detailObj.id === id
    })

    return (
        <div>
            <div>name:{name}</div>
            <div>grade:{nameGrade.grade}</div>
        </div>
    );
  }
}

        这种方法携带的参数不会显示到页面的地址栏中。

(1),携带参数;

<Link to={{pathname:'/student/grade/detail', state:{id:msgObj.id, name:msgObj.name}}}>{msgObj.name}</Link>

(2),声明接收,state方法也不需要声明接收;

<Route path="/student/grade/detail" component={Detail} />

(3),接收参数;

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

传递参数小总结:

(1),params方法和search方法会将携带的参数显示在地址栏中,state方法不会。

(2),params方法需要声明接收参数,search方法和state方法不需要声明接收,正常注册路由。

(3),三种方法刷新都可以保留参数,数据不会消失。

4,编程式路由导航

        编程式路由导航是借助this.props.history对象上的API操作路由跳转,前进,后退等。

import React, { Component } from 'react';

export default class Student extends Component {

  pushTeacher = () =>{
    this.props.history.push('/teacher')
  }
  
  render() {
    // console.log(this.props)
    return (
      <div>
        <h3>Student</h3>
        <button onClick={this.pushTeacher}>跳转到Teacher</button>
      </div>
        
    );
  }
}

         常用的有

push():历史记录是按栈的形式存放的,push方法在原先的基础上加入一条记录;

replace():会将原先记录栈顶的一条记录替换掉;

goBack():后退一条记录;

goForward():前进一条记录;

go():添加数字,1代表前进一条记录,-1代表后退一条记录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值