博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用 typescript 写 react-router 5
阅读量:4083 次
发布时间:2019-05-25

本文共 4942 字,大约阅读时间需要 16 分钟。

不再提倡中心化路由!嵌套路由不再是 
{ props.children } 的用法了。每个路由都是一个 React 组件。

react-router-dom

在 web 端使用,只需要导入这个包就可以了,因为它从 react-router 中拿过来了很多东西。

// @types/react-router-dom/index.d.tsexport { …… } from 'react-router';

然后看看常用的有哪些功能

HashRouter / BrowerRouter

理解为路由容器,被包裹在里面的子组件就可以使用自己定义的路由组件了。

// index.tsximport React from 'react';import ReactDOM from 'react-dom';import { HashRouter } from 'react-router-dom';import App from './App';ReactDOM.render(    
, document.getElementById('root'));

Route

路由组件,路由匹配时这个位置被渲染成相应的内容。

  • path 需要匹配的路径
  • component 匹配成功渲染的组件
  • exact 是否严格匹配

这个例子中,只有当路径为 /home 时才会匹配。若没有 exact 属性,那么当路径为 /home 时,//home这两个路由组件都会被渲染。

嵌套路由

v4 以上版本不再支持 { props.children } 的方式进行嵌套路由,而是直接把子路由组件放在父组件中需要渲染的位置。

// App.tsx
// Dashboard.tsx

这样的嵌套路由写法,需要保证父组件与子组件有相同的路由前缀(/),且父组件没有 exact 属性。(目的是先渲染父组件,再匹配父组件内部定义的子路由组件)

动态路由

和其他路由插件一样,使用冒号配置动态路由。

// Dashboard.tsx

/other/1 会匹配 /other 和 /other/:id 这两个路由组件,根据实际情况对 /other 路由组件设置 exact 属性。

useParams 获取路由参数

// @types/react-router/index.d.tsexport function useParams
(): { [p in keyof Params]: string };

useParams() 方法返回的是一个对象,直接取属性 TS 会提示空对象中不存在这个属性。按照 TS 的规范,可以在动态路由组件中,定义一个接口约定路由传递的参数。

// OtherDetail.tsximport React from 'react';import { useParams } from 'react-router-dom';interface RouteParams {    id: string}export default () => {    const params = useParams
(); return (
动态路由:{ params.id }
)}

props 获取路由参数

路由组件的 props 数据类型为 RouteComponentProps

// @types/react-router/index.d.tsexport interface RouteComponentProps
{ history: H.History; location: H.Location
; match: match
; staticContext?: C;}

其中 match 属性会用的比较多

// @types/react-router/index.d.tsexport interface match
{ params: Params; isExact: boolean; path: string; url: string;}

在动态路由 /other/1 中,props.match.url 的值为 /other/1props.match.path 的值为 /other/:id。获取 props.match.params 中的属性仍然需要告诉 TS 有哪些属性。

import React from 'react';import { RouteComponentProps } from 'react-router-dom';interface RouteParams {    id: string}export default (props: RouteComponentProps
) => { return (
动态路由:{ props.match.params.id }
)}

useRouteMatch 获取路由匹配信息

上面说到可以使用 props 获取到与路由相关的信息,其中包括了 matchparams 等,可以使用 props.match 获取路由的匹配信息。也可以使用 useRouteMatch 方法。

// @types/react-router/index.d.tsexport function useRouteMatch
( path?: string | string[] | RouteProps,): match
| null;

注意 useRouteMatch() 的返回值可能是 null,不能简单的通过 match.* 的形式访问。

// Other.tsximport React from 'react';import { useRouteMatch } from 'react-router';export default () => {    const match = useRouteMatch();    return (        
路由路径:{ match && match.url }
)}

useLocation 和 useHistory 的用法类似。

Switch

Switch 只会匹配子组件中的第一个路由组件。对于前面提到的,在不设置 exact 属性的前提下,/home 会同时匹配 / 和 /home 两个路由组件,使用 Switch 可以进行单一匹配,但与放置顺序也有关。

Link

封装了 <a> 标签的组件进行路由跳转。

to home

NavLink

与 Link 的用法类似,会默认给当前路由路径与 to 属性匹配的组件添加 active 类名。

to home
to other
to other/1

当点击 to other/1 链接时,to other 链接也会被添加上 active 类名,这与 Router 组件是类似的,所以对于这样的导航,通常需要添加 exact 属性。

Redirect

to 属性进行重定向,通常会用在 Switch 中,作为匹配失败的处理。

编程式路由

useHistory() 返回的 history 对象,调用 push 方法。

参数传递

params

// 路由组件
// Home.tsxinterface RouteParams { id: string}export default () => { const params = useParams
(); return (
{ params.id }
)}// Link 跳转
to home// history 跳转import { useHistory } from 'react-router-dom';export default () => { const history = useHistory(); const pushRouteParams = () => { history.push('/home/1') }; return (
);};

state

// 路由组件
// Home.tsximport { useLocation } from 'react-router-dom';export default () => { const location = useLocation(); return (
{ location.state && location.state.id }
)}// Link 跳转
to home// history 跳转history.push({ pathname: '/home', state: { id: 1 } })

query

// @types/historyexport interface Location {    pathname: Pathname;    search: Search;    state: S;    hash: Hash;    key?: LocationKey;}

location 对象没有 query 属性了,应该是不提供这个方法了吧……

push 和 replace

// Link 
// historyhistory.push(...)history.replace(...)

钩子函数

v4 之后不再提供 onEnteronUpdateonLeave等函数,而是在路由组件中分别对应 React 中的 componentDidMountcomponentDidUpdate 和 componentWillUnmount 等生命周期方法,这恰好就可以使用新特性 useEffect 进行替换了。

在路由组件内部使用 useEffect,配合 history.replace() 进行路由权限控制

const history = useHistory();const state = true;useEffect(() => {    if (!state) {        history.replace('/');    }});

也写成一个自定义 Hook,在多个路由组件中使用

function useUserRole(state: boolean) {    const history = useHistory();    useEffect(() => {        if (!state) {            history.replace('/');        }    });}useUserRole(false);

转载地址:http://ypqni.baihongyu.com/

你可能感兴趣的文章
如何在vue中判断用户是否登录,登录权限
查看>>
Vue.js面试题整理
查看>>
Vuex入门
查看>>
详解Vue路由钩子及应用场景
查看>>
使用Webpack的代码分离实现Vue懒加载(译文)
查看>>
H5获取用户位置API + 百度地图API介绍
查看>>
Vue—知识点整理
查看>>
前端面经-webpack
查看>>
webpack面试
查看>>
浅析Vue源码
查看>>
Vue 数据响应式原理
查看>>
JavaScript 之实现一个简单的 Vue
查看>>
Vue知识点整理(面试)
查看>>
带你用vue撸后台 系列
查看>>
带你用合理的姿势使用webpack4(上)
查看>>
带你用合理的姿势使用webpack4(下)
查看>>
用 Vue 编写一个长按指令
查看>>
你需要 Mobx 还是 Redux ?
查看>>
一篇文章理解Web缓存
查看>>
Node.js 框架对比之 Express VS Koa
查看>>