深入浅出React之第七章:使用React-Router实现多页面应用

现实中,应用往往包含很多功能,这些功能无法通过一个页面展示,所以应用往往是‘多页面应用’。而且,用户在这些页面之间来回切换,开发者要做的就是保证用户的操作顺畅。最好的解决办法就是虽然逻辑上是‘多页面应用’,但是页面之间的切换并不引起页面刷新,实际上是‘单页面应用’。

1. 传统的多页面实现方式

如果使用传统的多页面实现方式,那么每次页面切换都是一次网页刷新,每次页面切换都遵循以下步骤:

  • 浏览器的地址栏发生变化指向新的URL,于是浏览器发起一个http请求到服务器获取页面完整的HTML。
  • 浏览器获取到HTML内容后,解析HTML内容。
  • 浏览器根据解析的HTML内容确定还需要下载哪些其他资源,包括javascript,css等。
  • 浏览器会根据HTML和其他资源渲染页面内容,然后等待用户的其他操作。

2. React-Router

react-router库可以帮助我们创建react单页面应用。在学习react-router之前,我们首先要了解几个概念。

每个URL都包含域名部分和路径(path)部分,例如对于URL http://localhost:3000/home来说,路径部分是home,因为应用可能被部署在任何一个域名上,所以决定一个URL显示什么内容的只有路径部分,和域名和端口没有关系。根据路径找对应应用内容的过程,就是react-router的重要功能——路由。

2.1 路由

react-router提供了两个组件来完成路由功能,一个是Router,另一个是Route。前者Router在整个应用中只需要一个实例,代表整个路由器。后者Route则代表每一个路径对应页面的路由规则,一个应用中应该会有多个Route实例。

我们来用create-react-app构建一个简单的单页面应用。只包含三个界面,一个是代表主页的Home,对应的路径是home。一个是代表详情页的Detail,对应路径是detail。最后一个是提示用户资源不存在的NotFound

home.js

const Home=()=>{
    return (
        <div>Home</div>
    )
}

detail.jsnotfound.js代码同上。

react-router认为每个界面都是一个react组件,当然这个组件也可以包含很多子组件来构成一个复杂的页面。

当准备好三个界面之后,我们来定义一下路由规则:
Routes.js

import React from 'react';
import {Router,Route,browserHistory} from 'react-router';

import Home from './pages/Home.js';
import Detail from './pages/Detail.js';
import NotFound from './pages/NotFound.js';

const history = browserHistory;
const Routes=()=>(
    <Router history={browserHistory}>
        <Route path='home' component={Home}/>
        <Route path='detail' component={Detail}/>
        <Route path='*' component={NotFound}/>
    </Router>
)

Router实例包含三个Route子组件,分别完成三个路由规则,路径home被映射到Home组件,路径detail被映射到Detail组件,一个*通配符代表的是所有路径,被映射到NotFound组件。

注意:这里的*通配符这个Route实例必须要放在最后。因为react-router是按照Route在代码中的先后顺序决定匹配的顺序,如果把含有*通配符的Route组件放在最前面,那它对任何路径都是匹配成功的,后面的Route规则根本不会有机会匹配。那样所有的路径都会被映射到NotFound组件上。

最后,修改一下src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Routes from './Routes.js';

ReactDOM.render(
    <Routes />,
    document.getElementById('root')
);
1.2 路由链接和嵌套

如果能在这个单页应用中增加一个顶栏,包含所有页面的链接,这样只要所有的页面都包含这个顶栏,那么就可以方便的进行不同页面的切换了。

react-router提供了一个名为Link的组件来支持路由链接,Link的作用是产生HTML的链接元素,但是对这个链接元素的点击操作并不引起网页跳转,而是被Link截获操作,将目标路径发送给Router路由器,这样Router就知道让哪个Route下的组件显示了。

src/TopMenu/index.js

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

const view =()=>{
    return (
        <div>
            <ul>
                <li style={liStyle}><Link to='/home'>Home</Link></li>
                <li style={liStyle}><Link to='/detail'>Detail</Link></li>
            </ul>
        </div>
    )
}

Link组件的to属性指向一个路径,对应路径在src/Routes.js中有定义。在这里,两个Link分别指向homedetail。注意路径前面有一个'/'符号,代表从根路径开始匹配。

与此同时,react-router提供了嵌套功能,避免我们需要针对每个Route组件增加顶部导航栏组件。

src/app.js

import React from 'react';
import {view as TopMenu} from './TopMenu';

const App=({children})=>{
    return (
        <div>
            <TopMenu />
            <div>{children}</div>
        </div>
    )
}
export default App;

上面的代码虽然看不见Home,DetailNotFound,不过它们都作为App的子组件。children代表就是App的子组件,所以App的工作其实就是给其他页面增加一个TopMenu组件。

src/Routes.js

const Routes =()=>(
    <Router history={browserHistory}>
        <Route path='/' component={App}>
            <Route path='home' component={Home}/>
            <Route path='detail' component={Detail}/>
            <Route path='*' component={NotFound}/>
        </Route>
    </Router>
)

现在,假如在浏览器中访问http://localhost:3000/home,那么react-router在做路径匹配时,会根据'/home'中的'/'找到App组件,然后根据剩下来的home找到componentHomeRoute

然后,react-router会渲染外层Route相关的组件,但是会把内存Route的组件作为children属性传递给外层组件。所以,在渲染App组件的同时,渲染children属性也就把Home组件渲染出来了。最终,TopMenuHome组件都显示在了页面上。

1.3 默认链接

当路径为空时,应用也应该显示有意义的内容,通常对应主页内容。例如Home组件。

react-router提供了另外一个组件IndexRoute,就和传统的index.html是一个路径下的默认页面一样,IndexRoute代表一个Route下的默认路由。
代码如下所示:

src/Routes.js

const Routes =()=>(
    <Router history={browserHistory}>
        <Route path='/' component={App}>
            <IndexRoute component={Home}/>
            <Route path='home' component={Home}/>
            <Route path='detail' component={Detail}/>
            <Route path='*' component={NotFound}/>
        </Route>
    </Router>
)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值