typescript-react学习笔记3

1.介绍react-router

自从新版本(好像是4)发布后,如果我们想要在浏览器中使用react-router的话,那么所需要安装的依赖包是react-router-dom,同时为了增加对typescript的支持,我们还需要yarn add @types/react-router-dom –dev。

react-router-dom里面的两个关键性组件BrowserRouter和Route组件,其中BrowserRouter是top-level component,它会根据path来决定哪个子Route组件将会被渲染。下面是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import * as React from "react";
import * as ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";
import Page1 from "./page/1";
import Page2 from "./page/2";

const Routes: React.SFC = () => {
return (
<Router>
<div>
<Route path="/1" component={Page1} />
<Route path="/2" component={Page2} />
</div>
</Router>
);
}

// top-level component
ReactDOM.render(<Routes />, document.getElementById("root") as HTMLElement);

2.使用Link进行导航

不多说,来自react-router-dom,见例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import * as React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Page1 from "./page/1";
import Page2 from "./page/2";

const Routes: React.SFC = () => (
<Router>
<div className="header">
<Link to="/1">page1</Link>
<Link to="/2">page2</Link>
</div>
<div className="content">
<Route path="/1" component={Page1} />
<Route path="/2" component={Page2} />
</div>
</Router>
);

相比Link,它可以接受一个activeClassName作为props,能够更加方便的定制当前路由tab处于焦点状态时的样式效果。

4.路由通配符之RouteComponentProps

关键词:路由通配符;RouteComponentProps;props.match.params,下面是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import * as React from "react";
import { RouteComponentProps } from "react-router";

type Props = RouterComponentProps<{id: string}>; // 只能是string或者是undefined

const Page21 = React.SFC<Props> = props => {
return (<h1>{props.match.params.id}</h1>);
}

export default Page21;

// routes.ts
<Route exact={true} path="/2" component={Page2} />
<Route path="/2/:id" component={Page21} />

注意对于上面的这个例子,对于path是/2的这个Route,增加了一个exact={true},如果不加的话,那么对于路由/2/3 将会既渲染Page2组件同时也会渲染Page21组件。以及,路由通配符所对应的变量的数据类型要么是字符串类型或者是undefined,所以必要的话,使用的时候需要做一个类型转换。另外,如果你定义组件的state类型的话,但是在构造函数里面又没有初始化的话,将会报错,为了避免这种在构造函数可能无法获取到值的情况下,建议将这个state作为可选state。

5.Switch component

Switch component的作用,对于Switch component的子Route component来说,谁最先被匹配到,那么谁显示谁,并且最多匹配一个。我们可以使用Switch来做些什么呢?可以用来实现404页面效果,把404组件作为Switch组件的最后一个子Route即可。

1
2
3
4
5
6
7
8
9
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

<Router>
<Switch>
<Route path="/2" component={page2} />
<Route path="/2/:id" component={page21} />
<Route component={notFound} />
</Switch>
</Router>

6.Redirect之权限验证:

如果某个路由是必须要登录之后才能够访问到的话,那么很显然此时必须做一个登录状态的验证,如果没有登录的话,那么就跳转到登录页面,下面是一个示意例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { BrowserRouter as Router, Route, Redirect, Switch } from "react-router-dom";
// 省略page import

const Routes: React.SFC = () => {
const [ isLogin, setLogin ] = React.useState(false);
return (
<Router>
<Switch>
<Route path="/1">
{
isLogin ? <Page1 /> : <Redirect to="/login" />
}
</Route>
<Route path="/2" exact={true} component={Page2} />
<Route path="/2/:id" component={Page21} />
<Route path="/login" component={Login} />
<Route component={NotFound} />
</Switch>
</Router>
);
};

7.react-router-dom获取查询字符串

关键词:RouteComponentProps,props.location.search;而对于路由匹配来说,关键词则是RouteComponentProps,props.match.params

直接举例如下所示:

1
2
3
4
5
6
7
8
9
10
import * as React from "react";
import { RouteComponentProps } from "react-router-dom";

const Search: React.SFC<RouterComponentProps> = props => {
const obj = new URLSearchParams(props.location.search);
const what = obj.get("what") || "";
return (<h1>{what}</h1>);
}

export default React.memo(Search);

8.lazy load component

react16内置了对lazy component的支持,只有当在必要的时候才会加载对于的路由组件。关键词:Suspense,React.lazy,fallback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import * as React from "react";
const Suspense = React.Suspense;

const Page1 = React.lazy(() => import("./page/1"));

const Routes: React.SFC = () => (
<BrowserRouter>
<Switch>
<Route path="/1">
{
variable ?
<Suspense fallback={<h1>Loading</h1>}><Page1 /></Suspense>
:
<Redirect to="/login" />
}
</Route>
</Switch>
</BrowserRouter>
);