【REACT-路由 V5】

1. 安装路由

npm i react-router-dom@5

2. App.js引入路由并使用

import React, { Component } from 'react'
import {HashRouter,Route} from 'react-router-dom'//hash模式,路径中会带#号
import films from './views/Films'
import Cinemas from './views/Cinemas'
import Center from './views/Center'

export default class App extends Component {
  render() {
    return (
      <div>
        <HashRouter>
          <Route path="/films" component={films} />
          <Route path="/cinemas" component={Cinemas} />
          <Route path="/center" component={Center} />
        </HashRouter>
      </div>
    )
  }
}

3. 路由组件封装

3.1 新建文件夹router => 新建路由组件文件IndexRouter.js

import React, { Component } from 'react'
import {HashRouter,Route} from 'react-router-dom'
import films from '../views/Films'
import Cinemas from '../views/Cinemas'
import Center from '../views/Center'

export default class IndexRouter extends Component {
  render() {
    return (
      <div>
        <HashRouter>
          <Route path="/films" component={films} />
          <Route path="/cinemas" component={Cinemas} />
          <Route path="/center" component={Center} />
        </HashRouter>
      </div>
    )
  }
}

3.2 App.js中引入并使用路由组件

import React, { Component } from 'react'
import IndexRouter from './router/IndexRouter'

export default class App extends Component {
  render() {
    return (
      <div>
        其他内容
        <div>
          <IndexRouter />
        </div>
      </div>
    )
  }
}

4. 路由重定向

4.1 模糊匹配:路径中含有/,初次加载和刷新任意路由地址都会跳转到/films

import {HashRouter,Route,Redirect} from 'react-router-dom'
<HashRouter>
   <Route path="/films" component={films}/>
   <Route path="/cinemas" component={Cinemas}/>
   <Route path="/center" component={Center}/>

   {/* 模糊匹配,刷新页面后都会匹配到路径,下方有解决方案/*/}
   <Redirect from="/" to="/films" />
</HashRouter>

4.2 Switch解决上面的路由匹配问题

  • 使用switch进行包裹,只渲染匹配到的第一个路由
import {HashRouter,Route,Redirect,Switch} from 'react-router-dom'

<HashRouter>
	<Switch>
	   <Route path="/films" component={films}/>
	   <Route path="/cinemas" component={Cinemas}/>
	   <Route path="/center" component={Center}/>
	
	   {/* 模糊匹配,刷新页面后都会匹配到路径/*/}
	   <Redirect from="/" to="/films" />
   </Switch>
</HashRouter>

4.3 匹配不到路径,跳转notFound页面

  • 精确匹配:exact-只有在/下会跳转到指定路径
import React, { Component } from 'react'
import {HashRouter,Route,Redirect,Switch} from 'react-router-dom'
import films from '../views/Films'
import Cinemas from '../views/Cinemas'
import Center from '../views/Center'
import NotFound from '../views/NotFound'

export default class IndexRouter extends Component {
  render() {
    return (
      <div>
        <HashRouter>
          <Switch>
            <Route path="/films" component={films}/>
            <Route path="/cinemas" component={Cinemas}/>
            <Route path="/center" component={Center}/>

            {/* 模糊匹配,刷新页面后都会匹配到路径/*/}
            <Redirect from="/" to="/films" exact/>//精确匹配:exact-只有在/下会跳转到指定路径
			
			//当路径不存在时会自动跳转至notfound页面
            <Route component={NotFound}/>
          </Switch>
        </HashRouter>
      </div>
    )
  }
}

5. 嵌套路由

  • 在同一页面下想展示不同组件时使用
  • 嵌套路由需要在一级路由对应的组件内部进行编写

新建路由组件文件IndexRouter.js

import React, { Component } from 'react'
import {Route,Redirect,Switch} from 'react-router-dom'
import NowPlaying from '../views/flims/NowPlaying'
import CommingSoon from '../views/flims/CommingSoon'

export default class FilmsRouter extends Component {
  render() {
    return (
      <div>
        <Switch>
          <Route path="/films/NowPlaying" component={NowPlaying}/>
          <Route path="/films/CommingSoon" component={CommingSoon}/>
          <Redirect from="/films" to="/films/NowPlaying" />
        </Switch>
      </div>
    )
  }
}

Films.js中引用该二级路由

import React from 'react'
import FilmsRouter from '../router/FilmsRouter'

export default function Films() {
  return (
    <div>
      <div style={{background:'yellow',height:'300px'}}></div>
      
      <FilmsRouter />
    </div>
  )
}

6. 声明式导航与编程式导航

6.1 声明式导航(NavLink)

  • NavLink必须放在HashRouter标签中使用
  • 选中导航后标签样式名默认添加active,可通过activeClassName修改选中样式名
  • activeStyle-选中效果样式
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'

export default class Tabbar extends Component {
  render() {
    return (
      <div>
        <li>
          <a href='#/films'>电影</a>
        </li>
        <li>
          {/* 必须放在HashRouter标签中使用 */}
          <NavLink to="/cinemas" activeClassName='activePart'>影院</NavLink>
        </li>
        <li>
          <NavLink to="/center" activeStyle={{
		    fontWeight: "bold",
		    color: "red"
		  }}>我的</NavLink>
        </li>
      </div>
    )
  }
}

6.2 编程式导航(props.history.push)

import React,{useEffect,useState} from 'react'
import axios from 'axios'
import { NavLink,useHistory } from 'react-router-dom';

export default function NowPlaying(props) {
  const [list,setList] = useState([]);
  
  useEffect(()=>{
     //异步获取数据
     axios({
      url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=9261499",
      method:'get',
      headers:{
        'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"16745641013679850669801473","bc":"110100"}',
        'X-Host': 'mall.film-ticket.film.list'
      }
    }).then(res=>{
      setList(res.data.data.films)
    })
  },[])

  const history = useHistory();
  const handleChangePage = (id)=>{
    // window.location.href = "#/detail/"+id;
    // props.history.push("/detail/"+id);
    history.push("/detail/"+id);
    //类组件中使用this.props.history.push(`/路径${id}`)进行跳转
  }
  return (
    <div>
      {list.map(item => {
        return (
          // <div key={item.filmId}>
          //   <NavLink to={'/detail'+item.filmId}>{item.name}</NavLink>
          // </div>
          <div key={item.filmId} onClick={() => handleChangePage(item.filmId)}>{item.name}</div>
        )
      })}
    </div>
  )
}

7. 路由传参

建议使用动态路由,参数不会丢失

7.1 params(动态路由传参)

优势 : 刷新,参数依然存在
缺点 : 只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋。

<Route path="/detail/:id" component={Detail}/>
this.props.history.push("/detail/"+id);
this.props.match.params.id

7.2 query

优势:地址栏不显示参数,传递参数可传对象;
缺点:刷新地址栏,参数丢失

<Route path="/detail" component={Detail}/>
this.props.history.push({pathname:'/detail',query:{id:id}});
this.props.location.query.id

7.3 state

同query差不多,只是属性不一样,而且state传的参数是加密的,query传的参数是公开的,只需要把query改为state即可。

优势:地址栏不显示参数,传递参数可传对象
缺点:刷新地址栏,(hash方式会丢失参数,Browser模式不会丢失参数)

<Route path="/detail" component={Detail}/>
this.props.history.push({pathname:'/detail',state:{id:id}});
this.props.location.state.id

7.4 search

优势:地址栏显示参数,舒心不会丢失
缺点:只能传递字符串

<Route path="/detail" component={Detail}/>
this.props.history.push({pathname:'/detail',search:'?a=1&b=2'})
this.props.location.search

用location.search所获取的是查询字符串(?a=1&b=2),可以使用nodejs里的qs(原名querystring)

import React from 'react'
import qs from 'qs'//不用安装,直接引用

export default function Detail(props) {
  let search = props.location.search.slice(1);//去除?
  let newSearch = qs.parse(search);
  return (
    <div>
      {/* Detail-{props.match.params.id} */}
      {/* Detail-{props.location.query.id} */}
      {/* Detail-{props.location.state.id} */}
      Detail-{newSearch.id}
    </div>
  )
}

8. 路由拦截

进入我的信息页面前进行是否登录判断,再渲染不同的组件页面
注意:render方法渲染的组件需要层层传递props属性,这样在在center组件中可以使用路由的相关api,center中的子组件想要用路由api,也需要父组件传递props

<Route path="/center" render={(props)=>{
	return isAuth() ? <Center {..props}/> : <Redirect to="/login"/>
}}/>
<Route path="/login" component={Login}/>

9. 路由模式

  • HashRouter 地址含有#
  • BrowserRouter 地址不含# ,好看,会向后端发送请求要页面,如果后端没有对应的路径处理,就会报404错误
  • as 可以将引入模块进行重命名
import {HashRouter as Router } from 'react-router-dom'
<Router>
</Router>

10. withRouter

使用withRouter,组件内部会继承父组件的props,高阶组件原理

//路由
<Route path="/center" render={(props)=>{
	return isAuth() ? <Center/> : <Redirect to="/login"/>
}}/>
//Center组件
import React,{Component} from 'react'
import { withRouter } from 'react-router-dom'

// function Center (props){
//   return (
//     <div>
//       Center
//       <div onClick={()=>{
//         props.history.push('/filmsOrder');
//       }}>电影订单</div>
//     </div>
//   ) 
// }
// export default withRouter(Center)


class Center extends Component {
  render() {
    return (
      <div>
        Center
        <div onClick={()=>{
            this.props.history.push('/filmsOrder');
        }}>电影订单</div>
      </div>
    )
  }
}
export default withRouter(Center)
import React,{useEffect,useState} from 'react'
import axios from 'axios'
import { NavLink,useHistory,withRouter } from 'react-router-dom';

export default function NowPlaying(props) {
  const [list,setList] = useState([]);
  
  useEffect(()=>{
     //异步获取数据
     axios({
      url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=9261499",
      method:'get',
      headers:{
        'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"16745641013679850669801473","bc":"110100"}',
        'X-Host': 'mall.film-ticket.film.list'
      }
    }).then(res=>{
      setList(res.data.data.films)
    })
  },[])
  return (
    <div>
      {list.map(item => {
        return <WithFilmItem key={item.filmId} {...item}/>
      })}
    </div>
  )
}

function FilmItem(props){
  const handleChangePage = (id)=>{
    
    //1-动态路由传参(推荐使用,参数不会丢失)
    props.history.push("/detail/"+id);
    // <Route path="/detail/:id" component={Detail}/>
    // props.match.params.id
  }
  return <div onClick={() => handleChangePage(props.filmId)}>{props.name}</div>
}

const WithFilmItem= withRouter(FilmItem);

11. 路由组件api

// push: a-b-c 可以回到上一级
//replace: a-b-c 回不到上一级 适用于登录后,不需要重新回到登录页面
this.props.history.replace('/center')
// 前进
this.props.history.goForward();

// 回退
this.props.history.goBack();

// 向前或向后跳转制定步数
this.props.history.go(1);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值