React: 研究React Router的使用

一、简单介绍

在web开发者,我们可以看到许多的页面可以实现无缝跳转和切换,这些网站大多数都是由用户发送请求并打开若干个独立文件的一系列页面构成的,对于这些文件和资源,用户可以进行前进、回退、跳转等操作。但是,如果把这些操作放在单页面应用中执行的话,就会出现很多问题。因为单页面应用中,所有的内容都处于同一个页面中。JavaScript只负责数据的载入和UI的渲染,并没有承担历史记录、书签、前进、回退以及跳转等工作。其实,路由转发就是为了解决这种问题而生的。然后React并没有一个统一标准的router。不过,鉴于路由转发的重要性,目前React社区中有一个比较通用受欢迎的路由转发工具React Router。其中,React Router这个工具提供的HashRouter组件对于处理新项目或者不需要后端服务的小型客户端网站是非常好的工具,提供的BrowserRouter组件是大部分准备上线的网站应用首选的解决方案。现在,我们来慢慢解开它们的面纱。首先,我们要安装这个路由软件包,安装的命令行和安装结果如下所示:

//安装react-router-dom
npm install react-router-dom --save

 

 

二、构建应用

为了能够充分运用React-Router路由转发功能,我们需要先构建一个看似拥有很多页面其实它依然是单页面的应用程序。例如学校网站,一个主页面,它包括首页[School Home]、学校概况[School Profile]、结构设置[Structure settings]、学科建设[Subject construction]等模块页面。它们可以通过路由功能进行自由地切换。导航样式如下图:

根据上图可知,这是一个网站主页包含的四个模块构成的。每一个模块页面有自己的标题和跳转路径。而且每一个路径都是可以在浏览器地址栏上输入并实现路由转发的。当用户点击任何一个模块页面时,这个页面对应的路由就会被请求,继而完成该页面的渲染工作。这个页面的主体结构如下所示:

//主页面,下辖4个模块页面,分别对应自己的路由。其他模块的路径下的"#"符号必不可少。
* Main page                   http://localhost:3000/
    *   首页[School Home]:              http://localhost:3000/#/
    *   学校概况[School Profile]:        http://localhost:3000/#/school_profile
    *   结构设置[Structure settings]:    http://localhost:3000/#/structure_settings
    *   学科建设[Subject construction]:  http://localhost:3000/#/subject_construction    

现在导入react-router-dom框架中的HashRouter组件和Route组件来分别构建应用程序的根组件和定义模块组件的路径,代码如下:

schoolPart.js 模块组件

import React from 'react';

//首页[School Home]
export const SchoolHome = () =>
    <section className="schoolHome">
        <h1>首页</h1>
    </section>;

//学校概况[School Profile]
export const SchoolProfile = () =>
    <section className="schoolProfile">
        <h1>学校概况</h1>
    </section>;

//结构设置[Structure settings]
export const StructureSettings = () =>
    <section className="structureSettings">
        <h1>结构设置</h1>
    </section>;

//学科建设[Subject construction]
export const SubjectConstruction = () =>
    <section className="subjectConstruction">
        <h1>学科建设</h1>
    </section>; 

schoolPage.js 根组件

import React from 'react';
import {SchoolHome, SchoolProfile, StructureSettings, SubjectConstruction} from "./schoolPart";
import {HashRouter, Route} from 'react-router-dom';

//将HashRouter组件作为根组件
//通过Route给模块组件(子组件)定义路由路径
export const School = () =>
    <HashRouter>
        <div className="main">
            <Route exact path="/" component={SchoolHome} />
            <Route path="/school_profile" component={SchoolProfile}/>
            <Route path="/structure_settings" component={StructureSettings}/>
            <Route path="/subject_construction" component={SubjectConstruction}/>
        </div>
    </HashRouter>;

在应用程序的入口index.js文件,挂载根组件如下:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import {School} from './router/schoolPage'

//挂载根组件
window.React = React;
ReactDOM.render(
    <School/>,
    document.getElementById('root')
);

应用程序启动后,不会渲染单个组件,而是将渲染HashRouter组件,默认的渲染结果是首页如图1。当然,我们可以自己在地址栏上输入对应的路由进行渲染,如图2:

 

分析:这些路径会告知router当浏览器窗体地址栏会发生变化后会渲染那个组件。每个Route组件都包含path和component属性。当浏览器地址和path匹配时,相关的component将会被显示。当路径地址是“/”时,router将会渲染SchoolHome组件。当路径地址是/subject_construction,将会渲染SubjectConstruction组件。以此类推,输入哪一个组件的路径,就会渲染哪一个组件。注意,第一个组件有一个属性exact,这个属性表示只有当该组件的路径和根目录"/"精确匹配时,才会显示该组件。注意,在定义路由时,符号“#”必不可少,表示其他模块的组件路径路径。

 

三、导航菜单

在上面的第二步骤中,虽然我们已经实现了一个简单的单页面应用程序,但是过于粗糙。不同组件的渲染都需要重新手动去在地址栏输入对应的路由。我们可以对这个主页进行优化,通过nav标签和Link组件构建导航菜单。这个导航菜单中包含每条路径的链接,用户可以在网站主页上点击链接跳转到任意模块了。而且浏览器支持后退功能,可以帮助直接回退到主页。代码如下所示:

schoolPart.js 模块组件

import React from 'react';
import {Link} from "react-router-dom";

//首页[School Home]
const divStyle = {
    width:"50%",
    height:"100%",
    backgroundColor:'#00417A'
};

const navStyle = {
    display: 'flex',
    flexDirection: 'row',
    flexWrap: 'nowrap',
};

const linkStyle = {
    color:'white',
    fontSize:20,
    textAlign:'center',
    width: 200
};
export const SchoolHome = () =>
    <div className="schoolHome" style={divStyle}>
        <nav style={navStyle}>
            <Link style={linkStyle} to="/">首页</Link>
            <Link style={linkStyle} to="school_profile">学校概况</Link>
            <Link style={linkStyle} to="structure_settings">结构设置</Link>
            <Link style={linkStyle} to="subject_construction">学科建设</Link>
        </nav>
    </div>;

//学校概况[School Profile]
export const SchoolProfile = () =>
    <section className="schoolProfile">
        <h1>学校概况</h1>
    </section>;

//结构设置[Structure settings]
export const StructureSettings = () =>
    <section className="structureSettings">
        <h1>结构设置</h1>
    </section>;

//学科建设[Subject construction]
export const SubjectConstruction = () =>
    <section className="subjectConstruction">
        <h1>学科建设</h1>
    </section>;

演示结果

四、Router属性

React Router可以把属性传递给它渲染的组件。例如我们可以把每一个组件的路由的位置传递下去。根据这个位置,来判断用户手动输入的请求的地址是否是合法的,然后决定是否渲染404组件。这里,需要通过React Router的Switch组件来匹配路由,这个组件确保只会渲染HashRouter子组件的其中某一个组件。如果没有匹配到理由,就会选择最后的404组件进行渲染。如下所示:

schoolPart.js 模块组件

import React from 'react';

// 首页[School Home]
export const SchoolHome = ({location})  =>
    <section className="schoolHome">
        <h1>首页---{location.pathname}</h1>
    </section>;

//学校概况[School Profile]
export const SchoolProfile = ({location}) =>
    <section className="schoolProfile">
        <h1>学校概况---{location.pathname}</h1>
    </section>;

//结构设置[Structure settings]
export const StructureSettings = ({location}) =>
    <section className="structureSettings">
        <h1>结构设置---{location.pathname}</h1>
    </section>;

//学科建设[Subject construction]
export const SubjectConstruction = ({location}) =>
    <section className="subjectConstruction">
        <h1>学科建设---{location.pathname}</h1>
    </section>;

//页面没找到[404 Not Found]
export const NotFound = ({location}) =>
    <div className="notFound">
        <h1>Page Not Found At {location.pathname}</h1>
    </div>;

schoolPage.js 根组件

import React from 'react';
import {SchoolHome, SchoolProfile, StructureSettings, SubjectConstruction, NotFound} from "./schoolPart";
import {HashRouter, Route, Switch} from 'react-router-dom';

//通过Switch组件进行匹配,默认最坏情况下选择NotFound进行渲染
export const School = () =>
    <HashRouter>
        <div className="main">
            <Switch>
                <Route exact path="/" component={SchoolHome} />
                <Route path="/school_profile" component={SchoolProfile}/>
                <Route path="/structure_settings" component={StructureSettings}/>
                <Route path="/subject_construction" component={SubjectConstruction}/>
                <Route component={NotFound}/>
            </Switch>
        </div>
    </HashRouter>;

演示结果:参数确实传递下去了。图1是正确的渲染结果,图2中当输入错误的地址时,渲染了404组件页面。

 

 

五、嵌套组件

Route组件可以用于匹配特定的URL资源定位符后才渲染对应的组件,在上面的示例中已有实现。正式由于这个特性,开发者可以将Web应用组织成一定的层级机构,提高组件的复用率。在以前开发者要想实现web页面某些组件的复用,需要结合页面模板和母版页才能实现。这里就引入了一个页面模板的概念,而React组件本身就可以使用子属性合成模板,这就为开发者提供了极大地便利。这里我们将上面示例中导航模式改为左侧边栏,这个左侧栏需要一直保持不变也即作为模板组件使用,当点击左侧边栏任意选项时时,在右边显示对应的嵌套组件内容。大概的步骤如下:

1、创建主菜单组件:

//通过NavLink组件创建菜单组件
export const MainMenu = () =>
    <nav className="main_menu" style={navStyle}>
        <NavLink to='/' />
        <NavLink to="/school_home" activeStyle={selectedStyle} style={linkStyle}>
            <p>首页</p>
        </NavLink>
        <NavLink to="/school_profile" activeStyle={selectedStyle} style={linkStyle}>
            <p>学校概况</p>
        </NavLink>
        <NavLink to="/structure_settings" activeStyle={selectedStyle} style={linkStyle}>
            <p>结构设置</p>
        </NavLink>
        <NavLink to="/subject_construction" activeStyle={selectedStyle} style={linkStyle}>
            <p>学科建设</p>
        </NavLink>
    </nav>;

2、创建页面模板

//创建模板菜单
//MainMenu为菜单组件,所有的children子组件都会复用它
export const PageTemplate = ({children}) =>
    <div className="page" style={pageStyle}>
        <MainMenu />
        {children}
    </div>;

3、复用页面模板创建主菜单项:

// 采用了页面模板创建首页组件
// 首页[School Home]
export const SchoolHome = ()  =>
    <PageTemplate>
        <section className="schoolHome" style={section1Style}>
            <h1>首页</h1>
        </section>
    </PageTemplate>;

4、创建右边嵌套菜单组件

//NavLink组件:可以用来创建链接,并且在链接被激活时可以显示相应的样式
//activeStyle:可以用来设置链接激活或者被选中后的CSS样式
export const SubMenu = ({match}) =>
    <div className="sub_menu" style={subStyle}>
        <NavLink to="/school_profile" activeStyle={match.isExact && selectedStyle}  style={subLinkStyle}>
            <p>人文</p>
        </NavLink>
        <NavLink to="/school_profile/history" activeStyle={selectedStyle} style={subLinkStyle}>
            <p>历史</p>
        </NavLink>
        <NavLink to="/school_profile/scenery" activeStyle={selectedStyle} style={subLinkStyle}>
            <p>风景</p>
        </NavLink>
    </div>;

5、复用页面模板配置子菜单项:

//学校概况[School Profile],附带三个子菜单
export const SchoolProfile = () =>
    <PageTemplate>
        <section className="schoolProfile" style={section2Style}>
            <Route component={SubMenu} />
            <Route exact path="/school_profile" component={People}/>
            <Route path="/school_profile/history" component={History}/>
            <Route path="/school_profile/scenery" component={Scenery}/>
        </section>
    </PageTemplate>;

6、配置根组件路由

//现在每一个模块都有对应页面地址,可以直接在地址栏输入即可渲染对应的组件部分
export const School = () =>
    <HashRouter>
        <div className="main">
            <Route exact path="/school_home" component={SchoolHome} />
            <Route path="/school_profile" component={SchoolProfile}/>
            <Route path="/structure_settings" component={StructureSettings}/>
            <Route path="/subject_construction" component={SubjectConstruction}/>
        </div>
    </HashRouter>;

完整代码如下:

schoolMenu.js

import React from 'react';
import {NavLink} from "react-router-dom";


//----------------------------------------- 创建左侧菜单导航 -----------------------------------------------//
//页面左侧导航样式
const navStyle = {
    display: "flex",
    flexDirection:"column",
    height: 500,
    width: "20%",
    backgroundColor: "#00417A",
    color: "ghostwhite"
};

//链接样式
const linkStyle = {
    color:'ghostwhite',
    fontSize: 30,
    textAlign:'center',
    height:"25%",
    justifyContent:'center',
    alignItems: "center"
};

//菜单主页选中样式
const selectedStyle = {
    backgroundColor:'white',
    color:"slategray"
};

//NavLink组件:可以用来创建链接,并且在链接被激活时可以显示相应的样式
//activeStyle:可以用来设置链接激活或者被选中后的CSS样式
export const MainMenu = () =>
    <nav className="main_menu" style={navStyle}>
        <NavLink to='/' />
        <NavLink to="/school_home" activeStyle={selectedStyle} style={linkStyle}>
            <p>首页</p>
        </NavLink>
        <NavLink to="/school_profile" activeStyle={selectedStyle} style={linkStyle}>
            <p>学校概况</p>
        </NavLink>
        <NavLink to="/structure_settings" activeStyle={selectedStyle} style={linkStyle}>
            <p>结构设置</p>
        </NavLink>
        <NavLink to="/subject_construction" activeStyle={selectedStyle} style={linkStyle}>
            <p>学科建设</p>
        </NavLink>
    </nav>;


//------------------------------- 为左导航的"学校概况"选项创建右侧子菜单 -------------------------------------//

const subStyle = {
    display: "flex",
    flexDirection:"row",
    backgroundColor: "#00417A",
    width: "100%"
};

//链接样式
const subLinkStyle = {
    color:'ghostwhite',
    textAlign:'center',
    width:"34%"
};

//NavLink组件:可以用来创建链接,并且在链接被激活时可以显示相应的样式
//activeStyle:可以用来设置链接激活或者被选中后的CSS样式
export const SubMenu = ({match}) =>
    <div className="sub_menu" style={subStyle}>
        <NavLink to="/school_profile" activeStyle={match.isExact && selectedStyle}  style={subLinkStyle}>
            <p>人文</p>
        </NavLink>
        <NavLink to="/school_profile/history" activeStyle={selectedStyle} style={subLinkStyle}>
            <p>历史</p>
        </NavLink>
        <NavLink to="/school_profile/scenery" activeStyle={selectedStyle} style={subLinkStyle}>
            <p>风景</p>
        </NavLink>
    </div>;


//----------------------------------------- 创建通用菜单模板 -----------------------------------------------//

//模板的样式
const pageStyle = {
    display: "flex",
    height: "100%",
    backgroundColor:'#EEE'
};

//创建模板菜单
export const PageTemplate = ({children}) =>
    <div className="page" style={pageStyle}>
        <MainMenu />
        {children}
    </div>;
View Code

schoolPart.js

import React from 'react';
import {Route} from 'react-router-dom'
import {PageTemplate,SubMenu} from './schoolMenu'

//分组样式
const section1Style = {
    display: "flex",
    flexDirection: "column",
    flex: 1,
    alignItems: 'center',
    justifyContent:'center'
};
const section2Style = {
    display: "flex",
    flexDirection: "column",
    flex: 1,
    alignItems: 'center',
};

// 首页[School Home]
export const SchoolHome = ()  =>
    <PageTemplate>
        <section className="schoolHome" style={section1Style}>
            <h1>首页</h1>
        </section>
    </PageTemplate>;

//学校概况[School Profile],附带三个子菜单
export const SchoolProfile = () =>
    <PageTemplate>
        <section className="schoolProfile" style={section2Style}>
            <Route component={SubMenu} />
            <Route exact path="/school_profile" component={People}/>
            <Route path="/school_profile/history" component={History}/>
            <Route path="/school_profile/scenery" component={Scenery}/>
        </section>
    </PageTemplate>;

//结构设置[Structure settings]
export const StructureSettings = () =>
    <PageTemplate>
        <section className="structureSettings" style={section1Style}>
            <h1>结构设置</h1>
        </section>
    </PageTemplate>;

//学科建设[Subject construction]
export const SubjectConstruction = () =>
    <PageTemplate>
        <section className="subjectConstruction" style={section1Style}>
            <h1>学科建设</h1>
        </section>
    </PageTemplate>;


//------------------------------- 子菜单组件 -------------------------------------//
export const People = () =>
    <div>
        <h2 style={{textAlign:'center'}}>我们的 人文特色</h2>
        <p>
            一是要深入把握教学、科研与学科建设的辩证统一关系,协调推进,共同进步,为更好地迎接第五轮学科评估做准备。<br/>
            二是各学院要根据自身发展情况,明确定位,立足优势,走特色发展之路,提升学科专业的品牌建设,扩大自身在学科领域内的影响力。<br/>
            三是拓展对外交流合作,服务国家战略和区域发展需求;四是尊重人文社会科学发展规律,强化服务支撑,优化管理体制机制。
        </p>
    </div>;

export const History = () =>
    <div>
        <h2 style={{textAlign:'center'}}>我们的 历史传统</h2>
        <p>
            一是要深入把握教学、科研与学科建设的辩证统一关系,协调推进,共同进步,为更好地迎接第五轮学科评估做准备。<br/>
            二是各学院要根据自身发展情况,明确定位,立足优势,走特色发展之路,提升学科专业的品牌建设,扩大自身在学科领域内的影响力。<br/>
            三是拓展对外交流合作,服务国家战略和区域发展需求;四是尊重人文社会科学发展规律,强化服务支撑,优化管理体制机制。
        </p>
    </div>;

export const Scenery = () =>
    <div>
        <h2 style={{textAlign:'center'}}>我们的 美丽风景</h2>
        <p>
            一是要深入把握教学、科研与学科建设的辩证统一关系,协调推进,共同进步,为更好地迎接第五轮学科评估做准备。<br/>
            二是各学院要根据自身发展情况,明确定位,立足优势,走特色发展之路,提升学科专业的品牌建设,扩大自身在学科领域内的影响力。<br/>
            三是拓展对外交流合作,服务国家战略和区域发展需求;四是尊重人文社会科学发展规律,强化服务支撑,优化管理体制机制。
        </p>
    </div>;
View Code 

schooPage.js

import React from 'react';
import {SchoolHome, SchoolProfile, StructureSettings, SubjectConstruction} from "./schoolPart";
import {HashRouter, Route} from 'react-router-dom';

/*
*   现在每一个模块都有对应页面地址,可以直接在地址栏输入即可渲染对应的组件部分
*   可以给一级菜单再添加子菜单。
*
*   首页:      http://localhost:3000/#/school_home
*
*   学校概况:  http://localhost:3000/#/school_profile
*             人文:http://localhost:3000/#/school_profile
*             历史:http://localhost:3000/#/school_profile/history
*             风景:http://localhost:3000/#/school_profile/scenery
*
*   结构设置:  http://localhost:3000/#/structure_settings
*
*   学科建设:  http://localhost:3000/#/subject_construction
* */

export const School = () =>
    <HashRouter>
        <div className="main">
            <Route exact path="/school_home" component={SchoolHome} />
            <Route path="/school_profile" component={SchoolProfile}/>
            <Route path="/structure_settings" component={StructureSettings}/>
            <Route path="/subject_construction" component={SubjectConstruction}/>
        </div>
    </HashRouter>;
View Code 

index.js

import React from 'react';
import ReactDOM from 'react-dom';
// import App from './App';
import './index.css';

import {School} from './router/schoolPage'
window.React = React;

ReactDOM.render(
    <School/>,
    document.getElementById('root')
);
View Code

演示结果 

六、Router重定向

当应用的某些路由发生改变后,用户希望仍然能通过旧的路由访问原内容,这类似于书签的功能。在React Router中提供了Redirect组件进行路由的重定向。例如针对上面的某些链接使用Redirect进行重定向,如果用户在地址栏输入"http://localhost:3000/#/history",也能跳转到"http://localhost:3000/#/school_profile/history"。如下所示:

// 通过Switch组件进行匹配,默认最坏情况下选择NotFound进行渲染
// 使用Redirect进行重定向,用户在地址栏输入"http://localhost:3000/#/history",
// 也能跳转到"http://localhost:3000/#/school_profile/history"。
export const School = () =>
    <HashRouter>
        <div className="main">
            <Switch>
                <Route exact path="/" component={SchoolHome} />
                <Route path="/school_profile" component={SchoolProfile}/>
                <Redirect from="/history" to="/school_profile/history" />
                <Redirect from="/scenery" to="/school_profile/scenery" />
                <Route path="/structure_settings" component={StructureSettings}/>
                <Route path="/subject_construction" component={SubjectConstruction}/>
                <Route component={NotFound}/>
            </Switch>
        </div>
    </HashRouter>;

完整代码如下:

schoolPart.js

import React from 'react';

// 首页[School Home]
export const SchoolHome = ({location})  =>
    <section className="schoolHome">
        <h1>首页---{location.pathname}</h1>
    </section>;

//学校概况[School Profile]
export const SchoolProfile = ({location}) =>
    <section className="schoolProfile">
        <h1>学校概况---{location.pathname}</h1>
    </section>;

//结构设置[Structure settings]
export const StructureSettings = ({location}) =>
    <section className="structureSettings">
        <h1>结构设置---{location.pathname}</h1>
    </section>;

//学科建设[Subject construction]
export const SubjectConstruction = ({location}) =>
    <section className="subjectConstruction">
        <h1>学科建设---{location.pathname}</h1>
    </section>;

//页面没找到[404 Not Found]
export const NotFound = ({location}) =>
    <div className="notFound">
        <h1>Page Not Found At {location.pathname}</h1>
    </div>;
View Code

schoolPage.js

import React from 'react';
import {SchoolHome, SchoolProfile, StructureSettings, SubjectConstruction, NotFound} from "./schoolPart";
import {Switch, HashRouter, Route, Redirect} from 'react-router-dom';

// 通过Switch组件进行匹配,默认最坏情况下选择NotFound进行渲染
// 使用Redirect进行重定向,用户在地址栏输入"http://localhost:3000/#/history",
// 也能跳转到"http://localhost:3000/#/school_profile/history"。
export const School = () =>
    <HashRouter>
        <div className="main">
            <Switch>
                <Route exact path="/" component={SchoolHome} />
                <Route path="/school_profile" component={SchoolProfile}/>
                <Redirect from="/history" to="/school_profile/history" />
                <Redirect from="/scenery" to="/school_profile/scenery" />
                <Route path="/structure_settings" component={StructureSettings}/>
                <Route path="/subject_construction" component={SubjectConstruction}/>
                <Route component={NotFound}/>
            </Switch>
        </div>
    </HashRouter>;
View Code

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import {School} from './router/schoolPage'
window.React = React;
ReactDOM.render(
    <School/>,
    document.getElementById('root')
);
View Code

演示结果:发现在链接后缀输入/history后,立即回撤刷新,最终访问的是旧的/school_profile/history。

 

七、Router参数

React Router中的另外一个非常实用的功能就是配置路由时可以设置参数并进行传递。路由参数是可以从URL中获取参数的变量。它们在数据驱动的Web应用程序中非常有用,特别是在内容过滤和管理首页选项显示方面。Router参数允许用户获取它们的参数值。它们可以在路由中使用冒号进行定义。路由的参数可以是一个,也可以是多个。为路由配置参数和获取参数的实例如下所示:

一个参数时:

//为CustomComponent组件的路由配置参数id
<Route exact path="/:id" component={CustomComponent}/>

//CustomComponent组件获取它的参数id
const CustomComponent = ({match}) => <h1>{match.params.id}</h1>

//通过URL初始化
"http://localhost:3000/#/213221";

多个参数时:

//为Student组件的路由配置参数id,参数name, 参数grade
<Route path="/student/:id/:name/:grade" component={Student}/>

//Student组件获取它的参数id,参数name, 参数grade
const Student = ({match}) =>
    <ul>
        <li>id: {match.params.id}</li>
        <li>name: {match.params.name}</li>
        <li>grade: {match.params.grade}</li>
    </ul>;

//通过URL初始化
"http://localhost:3000/student/213221/xyq/5"

完整示例如下:

schoolPart.js

import React from 'react';

// 首页[School Home]
export const SchoolHome = ({match})  =>
    <section className="schoolHome">
        <h1>首页---id={match.params.id}</h1>
    </section>;

//学校概况[School Profile]
export const SchoolProfile = ({match}) =>
    <section className="schoolProfile">
        <h1>学校概况---id={match.params.id},name={match.params.name}</h1>
    </section>;

//结构设置[Structure settings]
export const StructureSettings = ({match}) =>
    <section className="structureSettings">
        <h1>结构设置---id={match.params.id},name={match.params.name}</h1>
    </section>;

//学科建设[Subject construction]
export const SubjectConstruction = ({match}) =>
    <section className="subjectConstruction">
        <h1>学科建设---id={match.params.id},name={match.params.name}</h1>
    </section>;
View Code

schoolPage.js

import React from 'react';
import {SchoolHome, SchoolProfile, StructureSettings, SubjectConstruction} from "./schoolPart";
import {HashRouter, Route} from 'react-router-dom';

//创建根组件,给子组件配置路由
export const School = () =>
    <HashRouter>
        <div className="main">
            <Route exact path="/:id" component={SchoolHome} />
            <Route path="/school_profile/:id/:name" component={SchoolProfile}/>
            <Route path="/structure_settings/:id/:name" component={StructureSettings}/>
            <Route path="/subject_construction/:id/:name" component={SubjectConstruction}/>
        </div>
    </HashRouter>;
View Code

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import {School} from './router/schoolPage'

//组件挂载
window.React = React;
ReactDOM.render(
    <School/>,
    document.getElementById('root')
);
View Code

演示结果: 可以看到,在使用URL初始化时,可以获取到输入的参数并显示

 

八、BrowserRouter

截止目前为止,在上面的示例中使用的一直都是HashRouter组件。HashRouter组件会自动在每一个路径前面添加一个“#”符号。为了让该router支持同构性,此时可以使用BrowserRouter组件来代替HashRouter组件,BrowserRouter组件会把“#”符号移除,HashRouter组件和BrowserRouter组件的使用方式基本是一样的。示例如下:

schoolPart.js

// 首页[School Home]
export const SchoolHome = ()  =>
    <section className="schoolHome">
        <h1>首页</h1>
    </section>;

//学校概况[School Profile]
export const SchoolProfile = () =>
    <section className="schoolProfile">
        <h1>学校概况</h1>
    </section>;

//结构设置[Structure settings]
export const StructureSettings = () =>
    <section className="structureSettings">
        <h1>结构设置</h1>
    </section>;

//学科建设[Subject construction]
export const SubjectConstruction = () =>
    <section className="subjectConstruction">
        <h1>学科建设</h1>
    </section>;
View Code

schoolPage.js

import React from 'react';
import {SchoolHome, SchoolProfile, StructureSettings, SubjectConstruction} from "./schoolPart";
import {BrowserRouter, Route} from 'react-router-dom';

export const School = () =>
    <BrowserRouter>
        <div className="main">
            <Route exact path="/school_home" component={SchoolHome} />
            <Route path="/school_profile" component={SchoolProfile}/>
            <Route path="/structure_settings" component={StructureSettings}/>
            <Route path="/subject_construction" component={SubjectConstruction}/>
        </div>
    </BrowserRouter>;
View Code

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {School} from './router/schoolPage'

window.React = React;
ReactDOM.render(
    <School/>,
    document.getElementById('root')
);
View Code

结果如下:可以发现如果URL中出现“#”符号会访问失败,相反移除“#”符号后,访问成功。

 

 

posted @ 2019-12-27 14:24  XYQ全哥  阅读(255)  评论(0编辑  收藏  举报