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

来源:互联网 发布:lol mac国服怎么取消了 编辑:程序博客网 时间:2024/06/10 17:09

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

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>)
原创粉丝点击