react-router > 4.0 路由

一、如何找到文档

在 GitHub 上直接搜索 react-router 进入,就能找到开发文档,
这里可以提供下,链接:https://reacttraining.com/react-router/

现在路由都是使用 react-router-dom 了。

二、路由容器

这个和以前 3.0 版本的路由配置不一样了,现在路由对应两种模式提供两个路由容器。

  • hashhistory
import { HashRouter as Router } from "react-router-dom";
  • browerhistory
import { BrowserRouter as Router } from "react-router-dom";

Vue 就一个路由容器 <router-view />

三、如何放置路由

react-router-dom 书写的路由方式是声明式,可以说是非常的难用,所以一般都是封装成类似 vue-router 路由书写方式。

<Router>
    <div>
        <Route path="/" render={() => <Child component={App} />} ></Route>
        <Route path="/" component={A} ></Route>
        <Route path="/" children={()=><A/>} ></Route>
        children为函数时不管path匹不匹配都会显示组件,如果不是函数显示效果和component相同
    </div>
</Router>

路由书写优先级为 component > render > children

四、路由跳转和传参

类似 Vue 中的 this.$router,react 路由参数主要包含四部分:

  1. history里面有push
  2. location 有query(search)和params(state)
location内容
{
    hash: ""
    pathname: "/about"
    search: ""
    state: {id: 10}
}
  1. match配置路由路径
  2. staticContext

路由跳转的两种方式:

  • 声明式
<Link to="/about?user=CondorHero">关于</Link>
<Link to={{pathname:"/about",search:"CondorHero"}}>关于</Link>
<Link to={{pathname:"/about",state:{id:10}}}>关于</Link>

比较特殊的还有一个 NavLink 导航链接,不同于 Link ,NavLink 可以增加样式。常用于单页面左侧导航。

<NavLink to="/about" style={{fontWeight: "bold",color: "red"}}>About</NavLink>
<NavLink to="/about" activeClassName="className">About</NavLink>

元素处于活动状态时应用于元素的样式, 可以行内也可以类名添加活动样式。

  • 编程式

push方法,两种配置方式能够 push ,一种是 <Route></Route> 包裹的组件,通过 this.props.history.push

另一种是通过,history 模块,或者是 useHistory 钩子。

五、重定向

新位置将覆盖历史记录堆栈中的当前位置,就像服务器端重定向(HTTP 3xx)一样。

import { Redirect } from "react-router-dom";
<Redirect to="/somewhere/else" />
//用法和Link一样

六、如何在任意组件找到 Vue this 上的路由对象

Vue 2.0 的路由是绑定在 this 的身上,React 路由只会出现在 和 <Route></Route> 绑定的组件内部,所以其他组件要想跳转路由并传参的话,两种办法。

  • history

注意⚠️这个 history 不是浏览器原生的。

import { createBrowserHistory , createHashHistory } from "history";

const customHistory = createBrowserHistory();

console.log(customHistory)
  • withRouter
import { withRouter } from "react-router-dom";

function Main(props){
  console.log(props)
  return (
    <div>
      <h1>你好</h1>
    </div>
  )
}

const A = withRouter(Main);

/*A仍然作为组件使用*/
<A></A>

七、路由钩子

这个路由钩子不是路由守卫,React-router 脑残,在 4.0 把路由拦截给删了,这里出现的路由钩子完全是针对 react-hook而言的路由hooks。react 版本要求大于 16.8。

  1. useHistory
import { useHistory } from "react-router-dom";
const history = useHistory();
history.push({pathname:"/index"})
  1. useParams

useParams返回URL参数的键/值对的对象。使用它来访问match.params当前<Route>,所以只对:

<Route path="/about/:slug" component={A} ></Route>

组件有效,push 或 params 携带参数都不行。

  1. useLocation

该useLocation挂钩返回location代表当前URL 的对象。

重点:配合 useEffect 可作为局部组件守卫使用。

  1. useRouteMatch

八、回到顶部

:root{
    scroll-behavior:smooth;
}
window.scrollTo(0,0);

九、路由精确匹配问题

react 路由默认是模糊匹配,例如:

<Route path="/" render={() => <B />} ></Route>
<Route path="/index" render={() => <index />} ></Route>
<Route path="/:user" render={() => <User />} ></Route>

输入 index 三个路径都会匹配。路由添加 exact(精确)属性可以精确匹配。必须是路径和大小写一样。

还有一个组件是 switch ,组件内部采用模糊匹配,但是只会匹配一个路由。

<Switch>
    <Route path="/" exact render={() => <B />} ></Route>
    <Route path="/index" render={() => <index />} ></Route>
    <Route path="/:user" render={() => <User />} ></Route>
</Switch>

十、静态化路由

相信你也发现了,嵌套路由写起来麻烦维护起来也麻烦。就没有类似 vue-router 那样数组的写法吗。还真没有需要自己来实现。但是官方也维护一个未来版 react-router-config 。不过实在是太简陋了。

一个简单的用法示例:
相对 Vue-Router 来讲:

  • 这个routes就相当于children
  • {renderRoutes(this.props.route.routes)} 就相当于 router-view

class B extends React.Component {
    constructor(props) {
        super(props);
        this.route = this.props.route;
    }
    render() {
        return (
            <div>
                <h1>B</h1>

                {renderRoutes(this.route.routes)}
            </div>
        )
    }
}
class Root extends React.Component {
    constructor(props) {
        super(props);
        this.route = this.props.route;
    }
    render() {
        return (
            <div>
                <h1>我是Root组件</h1>
                {renderRoutes(this.route.routes)}
                <h1>我是Root组件</h1>
            </div>
        )
    }
}

class Index extends React.Component {
    constructor(props) {
        super(props);
        this.route = this.props.route;
    }
    render() {
        return (
            <div>
                <h2>我是Index组件</h2>
                {renderRoutes(this.props.route.routes,{ someProp: "these extra props are optional" })}
            </div>
        )
    }
}
class Child extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <h3>我是child组件</h3>
                {renderRoutes(this.props.route.routes,{ someProp: "these extra props are optional" })}
                <h3>我是child组件</h3>
            </div>
        )
    }
}


const routes = [
    {
        component: Root,
        routes: [
            {
                path: "/",
                exact: true,
                component: Index
            },
            {
                path:"/B",
                component:B,
                routes: [
                    {
                        path: "/B/child",
                        component: Child
                    }
                ]
            }
        ]
    }
];




ReactDOM.render(
    <React.StrictMode>
        <Router>
            <div>
                {renderRoutes(routes)}
            </div>
        </Router>
    </React.StrictMode>,
    document.getElementById('root')
);

十一、路由即组件

react-router < 4.0 的时候,路由可以嵌套使用,现在已经不支持了:

<Router history={history}>
   <Route path="/" components={App}>//App组件里面有this.props.children
       <Route path="haha" component={Haha}></Route>
       <Route path="xixi" component={Xixi}></Route>
   </Route>
</Router>

用 Vue 的话讲就是:以前 this.props.children 是 router-view ,现在 Route 是 router-view

最后

还有一个知识点:PureComponent 和 Component 的区别?

PureComponent 只会在 state 和 props 不同才会更新。

参考:React 的 PureComponent Vs Component

当前时间 2020年5月5日 星期二 13:22:52

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266