My Little World

路由

为什么需要路由

1.单页应用需要进行页面切换
2.通过URL可以定位到页面
3.更有语义的组织资源

基本原理

在组件容器里根据URL决定显示什么样的组件

REACT router特性(和后端路由对比)

1.声明式路由定义

通过react组件标签进行声明,可以放在任何地方,不需要具体的路由表进行声明

2.动态路由

传统路由一旦配置了它就是一个配置文件,成为一个静态文件
而react router的路由是页面在render的时候才会被解析的,有相应路由的标记标签就是有相应的配置,没有标签就没有相应的配置

三种路由实现方式

  1. url路径:通过改变URl更改视图

    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
    28
    29
    30
    31
    32
    33
    34
    import React from "react";
    import { BroswerRouter as Router, Route, Link } from "react-router-dom";

    const Home = () => <h1>Home</h1>;
    const Hello = () => <h1>Hello</h1>;
    const About = () => <h1>About Us</h1>;

    export default class RouterSample extends React.PureComponent {
    render() {
    return (
    <Router>
    <div>
    <ul id="menu">
    <li>
    <Link to="/home">Home</Link>
    </li>
    <li>
    <Link to="/hello">Hello</Link>
    </li>
    <li>
    <Link to="/about">About</Link>
    </li>
    </ul>

    <div id="page-container">
    <Route path="/home" component={Home} />
    <Route path="/hello" component={Hello} />
    <Route path="/about" component={About} />
    </div>
    </div>
    </Router>
    );
    }
    }
  2. hash路由:使用Router 的HashRouter组件 进行路由容器包裹,切换路由时,
    具体的路径会被放在URl的#后面,通过改变hash更变视图《兼容低版本浏览器》

    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
    28
    29
    30
    31
    32
    33
    34
    import React from "react";
    import { HashRouter as Router, Route, Link } from "react-router-dom";

    const Home = () => <h1>Home</h1>;
    const Hello = () => <h1>Hello</h1>;
    const About = () => <h1>About Us</h1>;

    export default class RouterSample extends React.PureComponent {
    render() {
    return (
    <Router>
    <div>
    <ul id="menu">
    <li>
    <Link to="/home">Home</Link>
    </li>
    <li>
    <Link to="/hello">Hello</Link>
    </li>
    <li>
    <Link to="/about">About</Link>
    </li>
    </ul>

    <div id="page-container">
    <Route path="/home" component={Home} />
    <Route path="/hello" component={Hello} />
    <Route path="/about" component={About} />
    </div>
    </div>
    </Router>
    );
    }
    }
  3. 存路由:使用react-router 的MemoryRouter组件进行路由容器包裹,路由信息放在内存中管理,URL不变的情况下,即可进行视图切换

    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
    28
    29
    30
    31
    32
    33
    34
    35
    import React from "react";
    import { HashRouter as Router, Route, Link } from "react-router-dom";
    import { MemoryRouter } from "react-router";

    const Home = () => <h1>Home</h1>;
    const Hello = () => <h1>Hello</h1>;
    const About = () => <h1>About Us</h1>;

    export default class RouterSample extends React.PureComponent {
    render() {
    return (
    <MemoryRouter>
    <div>
    <ul id="menu">
    <li>
    <Link to="/home">Home</Link>
    </li>
    <li>
    <Link to="/hello">Hello</Link>
    </li>
    <li>
    <Link to="/about">About</Link>
    </li>
    </ul>

    <div id="page-container">
    <Route path="/home" component={Home} />
    <Route path="/hello" component={Hello} />
    <Route path="/about" component={About} />
    </div>
    </div>
    </MemoryRouter>
    );
    }
    }

基于路由配置进行资源组织 好处

1.实现业务逻辑的松耦合
2.易于扩展,重构和维护
3.路由层面实现Lazy Load

REACT Router API

1.:普通链接,会触发浏览器刷新
类似a标签,但是不会触发浏览器的刷新,点击时router会接管导航,对切换进行处理不会传递到浏览器,让其进行真正的页面切换
to属性代表链接到的URl的地址
2.:类似 Link但是会添加当前选中状态
可以添加activeClassName属性,当当前链接符合to属性值时,显示相应的样式 还有其他属性,详情请看react-router文档

1
<NavLink to="/faq" activeClassName='selected'>FAQs</NavLink>

3.:满足条件时提示用户是否离开当前页面
切换页面时,跟用户提供一个确认的操作

1
2
3
4
5
import { Prompt } from "react-router";
<Prompt
when={formIsHalfFilledOut}
message='Are you sure you want to leave'
/>

4.重定向当前页面,例如登录判断

1
2
3
4
5
6
7
8
import { Redirect,Route } from "react-router";
<Route exact path='/' render={()=>(
loggedIn?(
<Redirect to='/dashboard' />
) : (
<PublicHomePage/>
)
)}/>

5.:路由配置的核心标记,路径匹配时显示对应组件
path:路由
component:相应要显示的组件
exact:是否精准配置path
多个route path都符合当前路由时,那相应组件都会进行显示

1
<Route exact path="/" component={Home} />

6.:只显示第一个匹配的路由
找到一个匹配的路径就只显示这个路径相应的组件,其他组件不显示

1
2
3
4
5
6
7
import { Switch,Route } from "react-router";
<Switch>
<Route path="/home" component={Home} />
<Route path="/hello" component={Hello} />
<Route path="/about" component={About} />
<Route component={Nomatch} />
</Switch>

参数传递

通过URL传递参数 :
获取参数:this.props.match.params
页面状态尽量通过URl参数定义,方便页面间跳转时数据传递,否则需要将数据转化成组件内部state进行渲染,过程复杂

套嵌路由

1.每个React组件都可以时路由容器
2.React Router的声明式语法可以方便的定义嵌套路由

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import React from "react";
import {
BrowserRouter as Router,
Route,
Link
} from "react-router-dom";

const Category = ({ match }) => (
<h1>Sub Category {match.params.subId}</h1>
);

const SubCategory = ({ match }) => (
<div>
<h1>Category {match.params.id}</h1>

<ul id="menu">
<li>
<Link to={`/category/${match.params.id}/sub/1`}>
Sub Category 1
</Link>
</li>
<li>
<Link to={`/category/${match.params.id}/sub/2`}>
Sub Category 2
</Link>
</li>
<li>
<Link to={`/category/${match.params.id}/sub/3`}>
Sub Category 3
</Link>
</li>
</ul>
<div id="page-container-2">
<Route
path="/category/:id/sub/:subId"
component={Category}
/>
</div>
</div>
);

export default class NestedRoute extends React.PureComponent {
render() {
return (
<Router>
<div>
<ul id="menu">
<li>
<Link to="/category/1">Category 1</Link>
</li>
<li>
<Link to="/category/2">Category 2</Link>
</li>
<li>
<Link to="/category/3">Category 3</Link>
</li>
</ul>

<div id="page-container">
<Route
path="/category/:id"
component={SubCategory}
/>
</div>
</div>
</Router>
);
}
}