create-react-app 工程配置路由router(子路由)

蔺沛
2023-12-01

创建路由

运行在浏览器环境中,我们应当安装react-router-dom。react-router-dom暴露出react-router中暴露的对象与方法,因此你只需要安装并引用react-router-dom即可。

cnpm install -D react-router-dom

在index.js中添加

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// 路由使用 history模式
import { BrowserRouter } from 'react-router-dom';
// 路由采用 hash模式
// import { HashRouter } from 'react-router-dom'

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
, document.getElementById('root'));
  1. BrowserRouter 定义的是 history 模式
  2. HashRouter 定义路由采用的是 hash 模式

为什么要用 BrowserRouter 包裹 <APP>(根组件)?

  1. BrowserRouter 包裹的组件就可以使用Router相关的属性,即确定了路由的使用范围
  2. 放在根节点,说明路由是作用于整个工程的

hash模式 & history模式

  1. history模式
 import { BrowserRouter as Router } from 'react-router-dom'
  1. hash 模式
import { HashRouter  as Router } from 'react-router-dom' 
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// import { BrowserRouter as Router } from 'react-router-dom' //  history模式
import { HashRouter  as Router } from 'react-router-dom' // hash 模式
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
import reducer from './store/reduceIndex'

// createStore 第一参数是reducer(根据dispatch的type来改变state的方法)
// 第二个参数是 初始化state
// 第三个参数是 中间件函数
// const store = createStore(reducer, AppState);
const store = createStore(reducer);

ReactDOM.render(
    // 1. 路由采用history 模式
    // 2. 路由的作用范围,因为包裹了根节点,路由作用在整个项目中
    <Provider store={store}>
        <Router>
            <App />
        </Router>
    </Provider>
    ,
    document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

在根组件APP中设置路由

import React from 'react';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom';
import Login from './pages/loginPage'
import UserInfoPage from './pages/user/UserInfoPage'
import './App.css';

function App() {
  return (
    <div className="App">
		<Switch>
			<Route exact path='/' component={Login}/>
			<Route path='/UserInfoPage' component={UserInfoPage}/>
			<Redirect to='/' />
		</Switch>      
    </div>
  );
}

export default App;
  1. Switch: 是从上往下读,只要有一个匹配成功,就不会往下读
  2. exact 表示路径要与 path 字符串完全匹配
  3. Redirect 组件(重定向)到指定的 path 路径

如何理解 exact 属性 —— 精确匹配?

问题描述

先使用一个例子来说明

<div>
	<Route path="/login" component={Login}></Route>
	<Route path="/login/regist" component={Main}></Route>
	<Route path="/basicStudy" component={BasicStudy}></Route>
</div>

当地址栏的地址为 'http://localhost:3000/login/regist’的时候,会同时显示 Login 和 Main 组件

问题分析

因为/login/regist路径能够同时匹配 ‘/login’ 和 ‘/login/regist’,所以两个路径匹配的组件就全部显示出来了

解决办法

  1. 使用<Switch>组件只匹配最前面一个
<Switch>
	<Route path="/login" component={Login}></Route>
	<Route path="/login/regist" component={Main}></Route>
	<Route path="/basicStudy" component={BasicStudy}></Route>
</Switch>
  1. 使用 exact 属性,来匹配精确路径
<div>
	<Route exact path="/login" component={Login}></Route>
	<Route path="/login/regist" component={Main}></Route>
	<Route path="/basicStudy" component={BasicStudy}></Route>
</div>

嵌套子路由

  1. 父组件定义一个路由
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

render() {
    const { address, username } = this.state
    return (
      <div className="app">
        <div className="app--left">
          {this.getMenuHtml()}
        </div>
        <div className="app--content">
          <Switch>
            <Route path="/login" component={Login}></Route>
            <Route path="/main" component={Main}></Route>
            <Route path="/basicStudy" {...props} component={BasicStudy}></Route>
          </Switch>
        </div>
    </div>
    );
}
  1. /basicStudy 子组件定义一个路由
render() {
    const { address, username } = this.state
    return (
      <div >
        <button onClick={this.changeAddress.bind(this)}>改变地址</button>
        <Header {...this.props} sex='女' address={address}></Header>
        {/* 
        定义了两个 MainLayout,他们是两个双胞胎,但是不是同一个对象 
        在render函数中,定义的组件,实际上是 “new 组件名()返回对象”
        */}
        <MainLayout username={username} age='30'></MainLayout>
        {/* <MainLayout username={username} age='31'></MainLayout> */}
        <Footer ></Footer>
        {/* 显示变量需要使用{} */}
        {/* {name} ---- {myname}-----{age}-----{aaaa} */}
        <div >
          <Route path='/basicStudy/login' component={Login}/>
          <Route path='/basicStudy/main' component={Main}/>
        </div>
      </div>
    );
}
  1. 注意事项
    *. 父组件一定不能是 exact 属性修饰,因为子组件的路径一定要匹配父组件的路径,这样父组件才会显示出来,有了父组件之后才会有子组件
    *. 子路由定义的path还是绝对路径(包含父组件的路径地址)
    *. 如果想要从父组件的props中获取数据,使用 {…props}(个人感觉这个路由有点类似于 Vue中的 is 指令)
 类似资料: