0%

React——路由

路由的使用

  • 先在项目中下载react-router-dom
1
cnpm i react-router-dom --save
  • 在App下引入BrowserRouter跟Route,然后在渲染函数中使用这两个类
  • Route中的两个参数
    1. path:表示url路径
    2. component:表示这个Route是哪个组件的路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React from 'react';
import Home from './pages/home';
import Mine from './pages/mine';
import { BrowserRouter, Route, Link, Switch, NavLink } from "react-router-dom";
import MyNav from './components/mynav';

/**
* HashRouter:锚点路由
* BrowserRouter:h5新特性
*/

function App() {
return (
<div className="App">
<p>App</p>
{/* Route需要被BrowserRouter包含 */}
<BrowserRouter>
<MyNav/>
{/* <MyNavLink/> */}
<Route path="/home" component={Home}/>
<Route path="/mine" component={Mine}/>
</BrowserRouter>
</div>
);
}

export default App;
  • 当一个组件被声明为Route的属性值时,Route会把history、location、match三个对象放到props中并传递到组件中,这三个三对象的含义分别是:
    1. history:包含了组件可以使用的各种路由系统的方法,常用的有 push 和 replace,两者都是跳转页面,但是 replace 不会引起页面的刷新,仅仅是改变 url。
    2. location:相当于URL 的对象形式表示,通过 search 字段可以获取到 url 中的 查询字符串参数值的信息。
    3. match:包含了具体的 url 信息,在 params 字段中可以获取到各个路由节点参数的值。

BrowserRouter与HashRouter

  • BrowserRoute是H5的新特性,它在路由导航时,不需要加#
  • HashRouter时锚点路由,需要加#

Link跳转

  • Link一般用来做导航,创建一个组件,用来封装导航栏
  • Link的to属性表示跳转至哪个路由
  • 最后在App中引入这个组件即可
1
2
3
4
5
6
7
8
9
10
11
12
import React from "react"
import { Link } from "react-router-dom"
export default class MyNav extends React.Component{
render(){
return (
<ul>
<li><Link to="/home">Home页面</Link></li>
<li><Link to="/mine">Mine页面</Link></li>
</ul>
)
}
}

exact和strict精致匹配

  • 当path属性没有加exact的时候/mine和/mine/ucenter两个路由都会跳转到mine页面,其中/mine/ucenter中包含了两个页面
  • 如果只要每个路由的最后一个节点生效,则可加exact=true(exact默认为true)
  • 加上strict的目的是为了明确 [路由] 和 [路由]/ 的区别,若不加,这两个路由代表的是一个路由
1
2
3
4
5
6
7
8
//换成下面代码
<BrowserRouter>
<MyNav/>
{/* <MyNavLink/> */}
<Route strict exact path="/home" component={Home}/>
<Route strict exact path="/mine" component={Mine}/>
<Route path="/mine/ucenter" component={UCenter}/>
</BrowserRouter>

404页面和Switch

  • 创建一个简单的404页面组件,然后在App引入,这样404组件将会匹配任意路由
  • 其实这样是不对的,我们要使输入正确的路由时不出现NotFound页面,需要加上Switch标签
  • Switch表示BrowserRouter一次只能展现一个组件页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from "react"

export default function NotFound() {
return (
<div>
404页面
</div>
)
}
<BrowserRouter>
<MyNav/>
<Switch>
{/* <MyNavLink/> */}
<Route strict exact path="/home" component={Home}/>
<Route strict exact path="/mine" component={Mine}/>
<Route path="/mine/ucenter" component={UCenter}/>
<Route component={NotFound}/>
</Switch>
</BrowserRouter>
  • 如果加了Switch不加exact的话,则只有第一个节点生效,其他的不生效

render func

  • 在Route中可以使用render来替换component,render属性传入的是一个函数,render属性有两种使用方式
    1. 在render的函数中直接写html
    2. 在render的函数中写组件,间接渲染html,使用这种方式可以传入参数props,并可以和之前一样传递组件属性值,在组件中使用props来接收属性值
1
2
3
4
5
6
<Route path="/demo" render={()=>
<div>
Demo
</div>
}/>
<Route path="/demo" render={(props)=><Demo{...props} name="Hello"/>} />
1
2
3
4
5
6
7
8
9
10
11
import React from "react"

const Demo = (props)=>{
console.log(props)
return (
<div>
{props.name}, Demo
</div>
)
}
export default Demo
  • 一般情况下,我们在使用导航栏的时候,导航栏都会有一个高亮效果来表示被选中的项,这时就可以使用NavLink来替换Link
  • 要使活动项应用某些css样式,有三种方式:
    1. 默认方式,使用NavLink会让标签自动地给活动项添加class=”active”,则可以使用该class设置样式,适合样式较复杂且不同活动项有相同样式的情况
    2. 使用activeClassName属性,使活动项添加一个手动设置的类名,适合样式较复杂且不同活动项有不同样式的情况
    3. 使用activeStyle属性,可以,使活动项直接添加css样式,适合样式较少的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React from "react"
import { NavLink } from "react-router-dom"
import "./style.css"
export default class MyNavLink extends React.Component{
render(){
return (
<ul>
<li><NavLink activeClassName="selected" exact to="/">Home页面</NavLink></li>
<li><NavLink exact to="/mine">Mine页面</NavLink></li>
<li><NavLink activeStyle={{color:'green'}} to="/mine/ucenter">UCenter页面</NavLink></li>
<li><NavLink to="/demo">Demo页面</NavLink></li>
</ul>
)
}
}

读取Url参数

  • 在react中,如果要在Url再加上Url节点参数的话,可以在path属性中添加Url节点参数,例如:
1
2
//这里的/:id?/:name?都为节点参数,而其中的?代表该参数可以为空
<Route path="/demo/:id?/:name?" render={(props)=><Demo{...props} name="Hello"/>} />
  • 然后在Demo中就可以使用props.match读取这两个参数的值
1
2
3
//读取节点参数值
const id = props.match.params.id
const name = props.match.params.name

读取querystring参数

  • 在react中,如果要读取Url中查询字符串参数的值,则有两种方式可以读取:
    1. 使用URLSearchParams来读取
    2. 使用第三方库querystring来读取
1
2
3
4
5
6
7
8
9
//提取查询字符串参数值的第一种方式
const params = new URLSearchParams(props.location.search)
console.log(params.get("name"));
console.log(params.get("age"));
//提取查询字符串参数值的第二种方式
const querystr = props.location.search.replace('?', '')
const value = querystring.parse(querystr);
console.log(value.name);
console.log(value.age);
  • Link to-object可以设置path携带查询字符串,即在to属性中添加一些其他附带的值:
1
2
3
4
5
6
7
8
9
//这里的Url为http://localhost:3000/mine?sort=name#the-hash
//state是隐性携带的参数
<li><NavLink exact to={{
pathname: "/mine",
//默认查询字符串,search和hash是显性参数
search: "?sort=name",
hash: "#the-hash",
state:{ fromApp: true }//隐性参数
}}>Mine页面</NavLink></li>

Redirect重定向

  • 如果没有对一个组件声明一个路由,则可以使用Redirect来跳转页面,比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import React from "react"
import { Redirect, Prompt } from "react-router-dom"
export default class Shop extends React.Component{
constructor(){
super()
this.state = {
isLogin: true,
name:""
}
}
render(){
const isLogin = this.state.isLogin
//判断isLogin,为true则显示shop页面,为false则跳转到home页面
return (
<div>
{
isLogin ?
<div>
Shop
</div>
: <Redirect to="/"/>
}
</div>
)
}
}

withRouter

  • withRouter在react中是一个高阶组件,作用是将一个组件包裹进Route里面, 然后react-router的三个对象history, location, match就会被放进这个组件的props属性中
  • 则可以在这个组件中使用history, location, match这三个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from "react"
import { withRouter } from "react-router-dom";
class MineDemo extends React.Component{
clickHandler = ()=>{
console.log(this.props);
//使用history进行跳转
this.props.history.push("/")
}
render(){
return (
<div>
<button onClick={this.clickHandler}>回到home页面</button>
</div>
)
}
}
export default withRouter(MineDemo);

Prompt

  • Prompt可以用来触发提示信息,when属性表示触发的条件,而message表示提示信息的内容
1
2
3
4
//在这里,当name的值为空时跳转则不会触发提示信息,而不为空时则会触发提示信息
<Prompt when={ this.state.name }
message={ "你确定要离开吗?" }/>
<input type="text" value={this.state.name} onChange={(e)=>this.setState({name:e.target.value})}/>
-------------本文结束感谢您的阅读-------------