React-router学习笔记

项目地址

承接上一篇文章React学习笔记

安装

找到官方的github,可以看见更新到了4.0版本,虽然我也没有用过之前的版本。

这里有一个坑,虽然叫react-router,但是安装的是react-router-dom,因为官方教程,中引用的是react-router-dom

$ cnpm i -S react-router-dom

起步

引用方法,如官方文档所写

1
2
3
4
5
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'

如果有新标签,那么记得引入进来

创建一个简单的路由,我直接引用之前的React项目,继续编写

我在App.js下新建两个常量来装html标签

1
2
3
4
5
6
const Dom1 = () => (
<div>dom1</div>
)
const Dom2 = () => (
<div>dom2</div>
)

然后再class Apprender()中写到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
render() {
return (
<Router>
<div className="App">
<p onClick={this.qwe}>click</p>
<p>{this.state.title}</p>
<p>
<button onClick={ ()=>{ this.setState({ page: true }) }}>show hello</button>
<button onClick={ ()=>{ this.setState({ page: false }) }}>show world</button>
</p>
{
this.changePage()
}
<h1>下面是路由</h1>
<div>
<Link to="/dom1">dom1</Link>
<Link to="/dom2">dom2</Link>
</div>
<Route path="/dom1" component={Dom1} />
<Route path="/dom2" component={Dom2} />
</div>
</Router>
);
}

最先的Router标签只包裹了下面路由的一块,但是出现一个报错

emmmmm,好吧,把<Router>写在了最外面

Route

传值

各路由的这种发法都一样,在后面添加/:id这样的方式去传值

这里改动一下,将Dom1Dom2换成外部引入的方式,在src目录下新建一个文件夹views,然后写两个文件,Dom1.jsDom2.js

1
2
3
4
5
6
7
8
9
10
import React, { Component } from 'react';
import '../App.css';
export default class Dom1 extends Component {
render () {
return (
<div>dom1.id = {this.props.match.params.id}</div>
)
}
}

然后再App.js中引用即可,然后再render()里面做一个改动

1
2
3
4
5
6
7
<h1>下面是路由</h1>
<div>
<Link to="/dom1/123">dom1</Link>
<Link to="/dom2/456">dom2</Link>
</div>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />

模糊匹配

因为在React-router中默认的有模糊匹配,比如/hello会匹配到/

App.js中做一些修改

1
2
3
4
5
6
7
8
<h1>下面是路由</h1>
<div>
<Link to="/dom1/123">dom1</Link>
<Link to="/dom2/456">dom2</Link>
</div>
<Route path="/" render={ () => (<div>Hello React-router</div>)}/>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />

这个时候你就会在页面中发现,在这样的路由中,也匹配到了/

解决办法是加一条属性exact={true}true和false是需要用{}抱起来的,当变量写进去

1
2
3
4
5
6
7
8
<h1>下面是路由</h1>
<div>
<Link to="/dom1/123">dom1</Link>
<Link to="/dom2/456">dom2</Link>
</div>
<Route path="/" exact={true} render={ () => (<div>Hello React-router</div>)}/>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />

末尾斜杠的匹配

<Route />标签还有一个属性,strict,如果为true的时候,path="/one/"不匹配path="/one",但是可以匹配path="/one/two"

无障碍式导航,和vue的<router-link>是一个东西

地址

to属性可以使字符串,可以是对象,比如我把之前的例子改一下

1
2
3
4
5
6
7
8
<h1>下面是路由</h1>
<div>
<Link to="/dom1/123">dom1</Link>
<Link to={{ pathname:'/dom2/456', search:'?name=lyk'}}>dom2</Link>
</div>
<Route path="/" exact={true} render={ () => (<div>Hello React-router</div>)}/>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />

回退

如果将replact属性写在/dom3上面,那么从/dom3返回的时候,会跳过/dom3前面的一项去返回,比如路由是/dom1->/dom2->/dom3,返回时候就直接从/dom3->/dom1

1
2
3
4
5
6
7
8
9
10
<h1>下面是路由</h1>
<div>
<Link to="/dom1/123">dom1</Link>
<Link to={{ pathname:'/dom2/456', search:'?name=lyk'}}>dom2</Link>
<Link replace to="/dom3/789">dom3</Link>
</div>
<Route path="/" exact={true} render={ () => (<div>Hello React-router</div>)}/>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />
<Route path="/dom3/:id" component={Dom3}/>

这里需要注意的是,不是说把replace写在/dom3上面,/dom3就会跳过,而是跳过他前面那一项

就是<Link>的升级版

选中时可以改变类名

activeClassName可以给标签选中时添加一个类名

1
2
3
4
5
6
7
8
9
10
<h1>下面是路由</h1>
<div>
<NavLink activeClassName="navColor" to="/dom1/123">dom1</NavLink>
<NavLink activeClassName="navColor" to={{ pathname:'/dom2/456', search:'?name=lyk'}}>dom2</NavLink>
<NavLink activeClassName="navColor" replace to="/dom3/789">dom3</NavLink>
</div>
<Route path="/" exact={true} render={ () => (<div>Hello React-router</div>)}/>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />
<Route path="/dom3/:id" component={Dom3} />

activeStyle可以直接添加样式

1
<NavLink activeStyle={{fontSize: '30px'}} activeClassName="navColor" replace to="/dom3/789">dom3</NavLink>

选中导航时做点儿别的

isActive决定导航是否激活,或者在导航激活时候做点别的事情。不管怎样,它不能决定对应页面是否可以渲染。

1
<NavLink isActive={ (match, location)=> { console.log(match); console.log(location); return match}} activeStyle={{fontSize: '30px'}} activeClassName="navColor" replace to="/dom3/789">dom3</NavLink>

切换路由的时候,都会触发这儿函数,虽然不是进入或者离开/dom3,就在/dom1dom2之间切换

Switch

只会渲染出来一个相匹配的标签,比如说你的地址是/dom1,然而你的路由有两个/dom1/:id,这个时候,这个‘dom1’是路径还是id?

这个时候我先把之前的/路由改动一下

1
2
3
4
5
6
7
8
9
10
<h1>下面是路由</h1>
<div>
<NavLink activeClassName="navColor" to="/dom1/123">dom1</NavLink>
<NavLink activeClassName="navColor" to={{ pathname:'/dom2/456', search:'?name=lyk'}}>dom2</NavLink>
<NavLink isActive={ (match, location)=> { console.log(match); console.log(location); return match}} activeStyle={{fontSize: '30px'}} activeClassName="navColor" replace to="/dom3/789">dom3</NavLink>
</div>
<Route path="/:id" render={ (location) => (<div>Hello React-router.id = {location.match.params.id}</div>)}/>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />
<Route path="/dom3/:id" component={Dom3}/>

这个时候就会发现,/:id这个路由也会被加载,而且后面一项当做‘id’,但是用<Switch>标签的话

1
2
3
4
5
6
7
8
9
10
11
12
13
<h1>下面是路由</h1>
<div>
<NavLink activeClassName="navColor" to="/dom1/123">dom1</NavLink>
<NavLink activeClassName="navColor" to={{ pathname:'/dom2/456', search:'?name=lyk'}}>dom2</NavLink>
<NavLink isActive={ (match, location)=> { console.log(match); console.log(location); return match}} activeStyle={{fontSize: '30px'}} activeClassName="navColor" replace to="/dom3/789">dom3</NavLink>
<NavLink to="/qwe/ewq">一个匹配不到的标签</NavLink>
</div>
<Switch>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />
<Route path="/dom3/:id" component={Dom3} />
<Route path="/:id" render={ (location) => (<div>Hello React-router.id = {location.match.params.id}</div>)}/>
</Switch>

这里需要注意一下,<Switch>标签里面是从上到下开始查找,如果前面的匹配到了,那么就不会向下了。感觉这个可以做404页面呀!

Redirect

重定向,和vue里面的重定向一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<h1>下面是路由</h1>
<div>
<NavLink activeClassName="navColor" to="/dom1/123">dom1</NavLink>
<NavLink activeClassName="navColor" to={{ pathname:'/dom2/456', search:'?name=lyk'}}>dom2</NavLink>
<NavLink isActive={ (match, location)=> { console.log(match); console.log(location); return match}} activeStyle={{fontSize: '30px'}} activeClassName="navColor" replace to="/dom3/789">dom3</NavLink>
<NavLink to="/qwe/ewq">一个匹配不到的标签</NavLink>
<NavLink to="/asd">重定向/asd -> /dom1</NavLink>
</div>
<Switch>
<Route path="/dom1/:id" component={Dom1} />
<Route path="/dom2/:id" component={Dom2} />
<Route path="/dom3/:id" component={Dom3} />
<Route path="/asd" render={ ()=>( <Redirect push={true} to="/dom1/123" />)} />
<Route path="/:id" render={ (location) => (<div>Hello React-router.id = {location.match.params.id}</div>)}/>
</Switch>

这个标签有一些属性:

  • to :要重定到的路径
  • push : 为真时就无法使用后退键了,永远在这里重定到的页面
  • from : 将要被重定的路径

Prompt

用户离开页面的时候可以发生一些事

需要做的事写在message属性里面

1
<Prompt message={ ()=>{ console.log('bye')}} />

or

1
<Prompt message="bye!" />

我,曼妥思,打钱