React 路由

作者: CondorHero | 来源:发表于2019-08-19 00:10 被阅读0次
一、路由使用起步配置

安装两个依赖:

npm install --save react-router
npm install --save react-router-redux

配置路由的时候参考npm文档:

https://www.npmjs.com/package/react-router-redux

官方的一个小 demo :

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'
import { Router, Route, browserHistory } from 'react-router'
import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
 
import reducers from '<project-path>/reducers'
 
// Add the reducer to your store on the `routing` key
const store = createStore(
  combineReducers({
    ...reducers,
    routing: routerReducer
  })
)
 
// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(browserHistory, store)
 
ReactDOM.render(
  <Provider store={store}>
    { /* Tell the Router to use our enhanced history */ }
    <Router history={history}>
      <Route path="/" component={App}>
        <Route path="foo" component={Foo}/>
        <Route path="bar" component={Bar}/>
      </Route>
    </Router>
  </Provider>,
  document.getElementById('mount')
)

在 React 应用中,通常会用 <Router /> 包裹 <Route />。 如此,当 URL 变化的时候,<Router /> 将会匹配到指定的路由,然后渲染路由绑定的组件。 <Route /> 用来显式地把路由映射到应用的组件结构上。 用 path 指定 URL,用 component 指定路由命中 URL 后需要渲染的那个组件。

实际使用就得按照此写法进行灵活配置,用到项目中我们需要把它给拆分灵活用到各个地方。

先来看下项目的目录结构:


目录结构

首先的配置主入口文件 main.js :

import React from "react";
import ReactDom from "react-dom";
import { createStore } from 'redux';
import { Provider } from 'react-redux';
// 以上均是常规配置项
// Router用来包裹路由route路由路径和对应的组件
// browserHistory,hashHistory路由采用是路径形式还是采用hash#形式
import { Router, Route, browserHistory,hashHistory } from 'react-router';
// syncHistoryWithStore同步路由到store里面,然组件可以访问
// routerReducer是具体的执行者,在combineReducers里面起作用
import { syncHistoryWithStore, routerReducer } from 'react-router-redux';

// 引入纯函数
import reducers from "./reducers";
// 需要使用的组件
import App from "./views/App";
import Xixi from "./views/Xixi";
import Haha from "./views/Haha";
import Son from "./views/Son";
// 创建仓库
const store = createStore(reducers);
 
// 路由同步到仓库里面
const history = syncHistoryWithStore(hashHistory, store);

// Route平级就是同级路由
// 嵌套就是层级路由
ReactDom.render(
    <Provider store={store}>
        <Router history={history}>
            <Route path="/" component={App}>
                <Route path="/haha" component={Haha}></Route>
                <Route path="/son" component={Son}></Route>
            </Route>
            <Route path="/xixi" component={Xixi}></Route>
        </Router>
    </Provider>
,document.querySelector("#app"));

再在 reducer 里面配置一下 routing

import {combineReducers} from "redux";
import reducer from "./reducer";
import { routerReducer } from 'react-router-redux';

export default combineReducers({
    reducer,
    routing: routerReducer
});

这时访问二级路由发现并没有二级路由的页面,关键的在一级目录里面配置这条命令:

import React, { Component } from 'react'

export default class App extends Component {
    render() {
        return (
            <div>
                <h1>我是最大的组件APP</h1>
                {this.props.children}//双标签里面的内容
            </div>
        )
    }
}

配置完毕的运行发现出现警告:

WARNING in ./main.js 11:37-51
"export 'browserHistory' was not found in 'react-router'
i 「wdm」: Compiled with warnings.

react-router 里面找不到 browserHistory。怀疑可能是安装包冲突的原因。
进入 node_modules\react-router-redux 检查 package.json 检查依赖的 react-router 最高支持到 "react-router": "^3.0.0" 而我们安装的是 "react-router": "^5.0.1"版本冲突了,现在卸载重装低版本的。

卸载命令:

npm uninstall react-router

重装指定版本:

npm install --save react-router@3

再次运行即可访问路由。

访问二级路由页面 son 这个页面:
http://127.0.0.1:8080/#/son


son.js 代码:
import React, { Component } from 'react';
import {connect} from "react-redux";

@connect(
    ({routing})=>({
        routing
    })
)
export default class Son extends Component {
    render() {
        return (
            <div>
                <h1>我是son组件</h1>
                {JSON.stringify(this.props.routing)}
            </div>
        )
    }
}
代码优化

把路由给提取出来,作为一个单独文件,因为路由里面要用到 history 而 history 又要用到 store ,store又必须放在首页,所以如果暴露的是组件就得用 props 传参,如果是函数那就用函数传参。这里暴露成函数。

路由文件 router.js

import React from "react";
import { Router, Route } from 'react-router';
// 需要使用的组件
import App from "./views/App";
import Xixi from "./views/Xixi";
import Haha from "./views/Haha";
import Son from "./views/Son";

var router;
export default router = (history)=> <Router history={history}>
    <Route path="/" component={App}>
        <Route path="/haha" component={Haha}></Route>
        <Route path="/son" component={Son}></Route>
    </Route>
    <Route path="/xixi" component={Xixi}></Route>
</Router>

相应的 main.js 就减负变成了:

import React from "react";
import ReactDom from "react-dom";
import { createStore } from 'redux';
import { Provider } from 'react-redux';
// 以上均是常规配置项
// Router用来包裹路由route路由路径和对应的组件
// browserHistory,hashHistory路由采用是路径形式还是采用hash#形式
import { Router, Route, browserHistory,hashHistory } from 'react-router';
// syncHistoryWithStore同步路由到store里面,然组件可以访问
// routerReducer是具体的执行者,在combineReducers里面起作用
import { syncHistoryWithStore, routerReducer } from 'react-router-redux';

// 引入纯函数
import reducers from "./reducers";

// 创建仓库
const store = createStore(reducers);

import router from "./router";
// 路由同步到仓库里面
const history = syncHistoryWithStore(hashHistory, store);

// Route平级就是同级路由
// 嵌套就是层级路由
ReactDom.render(
    <Provider store={store}>
        {router(history)}
    </Provider>
,document.querySelector("#app"));
二、子路由的两种书写方法

在书写子路由的时候,我们常用的方法是两种,第一种就是嵌套法。第二种就是外包法。两种方法各有优劣,看个人喜好,不过原理大致都是相同的。

  • 路由嵌套
<Router history={history}>
    <Route path="/" component={App}>
        <Route path="/haha" component={Haha}></Route>
        <Route path="/son" component={Son}></Route>
    </Route>
    <Route path="/xixi" component={Xixi}></Route>
</Router>

这种很常规,一层套一层的书写下去。

  • 外包法
<Router history={history}>
    <Route path="/" component={App}></Route>
    <Route path="/haha" component={Haha}></Route>
    <Route path="/xixi" component={Xixi}></Route>
</Router>

这种书写就是平行结构的了,这个写法特别像 Promise 解决异步回到黑洞的感觉。
同时要注意的是路由到的文件要想显示父路由的内容的使用父标签来包裹子标签。这就是外包法的本质。就像上面路由到 haha 这个路由,同时我也想显示 / 跟路由对应的 APP 组件。就得这样写:
haha.js

import React, { Component } from 'react'
import App from "./App";
export default class Haha extends Component {
    render() {
        return (
            <App>
                <h1>我是哈哈组件</h1>
            </App>
        )
    }
}

父组件 App.js 有 this.props.children 会把 haha.js 的内容放到 App.js 里面显示。

三、路由跳转

点击按钮或标签能够跳到不同 URL 对应的组件。一共两种方法:

  • Link 方法(属于react-router)
    这里的 Link 其实和 a 标签差不多。
    修改 HaHa.js 组件
import React, { Component } from 'react';
// 首先我们需要Link
import {Link} from 'react-router';
import App from "./App";
export default class Haha extends Component {
    render() {
        return (
            <App>
                <h1>我是哈哈组件</h1>
                {/* 把 <Link> 其实就是 <a> */}
                <Link to = "/">点击回到首页</Link>
            </App>
        )
    }
}

路由到 HaHa 的路由路径变为了:

<Route path="/students/haha" component={Haha}></Route>
Link组件跳转.gif
  • dispatch 方法(react-router-redux)

参考 npm react-router-redux 官网案例如下:

import { createStore, combineReducers, applyMiddleware } from 'redux';
import { routerMiddleware, push } from 'react-router-redux'
 
// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
  reducers,
  applyMiddleware(middleware)
)
 
// Dispatch from anywhere like normal.
store.dispatch(push('/foo'))

接下来我们需要把它配置到自己的项目上。main.js 配置中间件,自己找个地方放代码:

import { routerMiddleware } from 'react-router-redux';
const middleware = routerMiddleware(hashHistory);
const store = createStore(reducers,applyMiddleware(middleware));

配置完成在我们子组件中就可以引入 push 发送进行跳转了。

import React, { Component } from 'react';
import {connect} from 'react-redux';
import {push} from 'react-router-redux';
import App from "./App";

@connect(
    ({reducer})=>({
        reducer
    }),
    dispatch=>({
        dispatch
    })
)
export default class Haha extends Component {
    render() {
        return (
            <App>
                <h1>我是哈哈组件</h1>
                <button onClick = {()=>{
                    this.props.dispatch(push('/'));
                }}>按我跳转</button>
            </App>
        )
    }
}

至于两个跳转方法用的地方,Link 一般用来替代 a 标签,dispatch 往往使用事件进行控制。自己和酌情使用。

四、重定向(Redirect)跳转

这个东西特别类似服务器的 301 重定向功能。
我们现在使用子组件的 dispatch 功能调到一个假路由:

this.props.dispatch(push('/wu'));

很明显路由到这个地方什么组件也没有,我们给他重定向到首页:

<Redirect from = "/wu" to = "/"></Redirect>

这时就会自动跳到首页了。
from
你想由哪个路径进行重定向,包括动态段。
to
你想重定向的路径。

query
默认情况下,query 的参数只会经过,但如果你需要你可以指定它们。

四、<Route path="messages/:id" component={Message} />

相关文章

  • react从0到1的探索记录04

    18、React中的路由 React中路由的基本使用 在react中使用路由首先需要安装react的路由模块 np...

  • react学习资料八

    路由 使用react的路由就要引入react路由插件react-router.js ReactRouter 保存一...

  • React-Router知识点

    路由的分类 页面路由 hash 路由 h5路由 react路由 react-router-dom 路由方式 h5路...

  • React路由

    React 路由 一、在React中使用react-router-dom路由 安装npm install reac...

  • 有标题的文章

    React Redux 路由设计 - - React

  • React路由

    React路由 一、路由的形式 hash路由 : HashRouter history路由 : BrowserRo...

  • react-router Q & A

    什么是React 路由? React 路由是一个构建在 React 之上的强大的路由库,它可以让你向应用中快速地添...

  • 2018-12-21路由

    1.路由 React路由依赖于React Router,React Router保持UI和与URL的同步。它拥有简...

  • react-router-dom 的基本使用

    本文介绍 react 中路由的使用。在 react 中使用 路由的库为 react-router。或者是 reac...

  • react-router

    React Router 是完整的 React 路由解决方案 import React from 'react' ...

网友评论

    本文标题:React 路由

    本文链接:https://www.haomeiwen.com/subject/ohuhsctx.html