React Router 4.0 基本使用
路由的概念,起初来源于服务端,就是当浏览器访问一个网站的不同页面时,服务端能够正确的返回页面的内容。当访问首页时,它能返回首页的内容,访问关于我们页面时,返回关于我们的内容。可以看到路由就是一种控制和匹配,从而保证页面内容和页面的地址一一对应的关系。但是每次页面地址发生变化,服务端都会返回一个新的页面,从而导致整个页面重新加载,用户体验不好。所以就兴起了单页应用,所有的内容都在一个页面上进行展示,页面中的变化也是局部变化,不用再刷新整个页面。那局部变化是怎么实现的呢?也就是说,当点击Home时,怎么才能正确的渲染出Home的内容,而不是其它的内容, 当点击about时,怎么才能渲染出About 内容。
其实这里和服务端路由是一个道理,在服务端路由时,点击home页面时,我们是向服务端发送一个请求,告诉服务端,我们需要home页面。在单页应用中,我们虽然不用向服务器发送请求,但我们还是要标识一下我们的请求,我们想要home的内容。这也很好理解,如果我们都不知道需要什么内容,那还怎么展示内容。 怎么标识我们的请求呢? 这里还是和服务器路由一样,浏览器的地址栏,就是改变window.location 的值。但这里要注意的是,地址栏的变化,不应该导致向服务器发送请求。这里有两种方法可以实现,一种是hash, location 对象有一个hash属性,hash值变化了,location 也就发生变化了,但hash的变化不会向服务器发生请求,这符合我们和要求。如在浏览器地址栏中显示#home, 则表示我们想进入home 的内容。 另一种是h5 的history API, history 对象一个pushState 方法,它可以改变location 对象的值,而不会向服务器发送请求。history.pushState({url: ‘home’}), 浏览器地址发生变化,但没有像服务器发送请求。
现在我们标识了请求,那就要处理请求,就像服务器返回页面一样,我们也要正确渲染相对应的内容,所以就要做控制和匹配,保证标识的请求和渲染的内容一致。由于这些匹配和控制是在客户端完成的,所以叫做客户端路由。
首先要做的就是匹配, 当用户标识请求时,返回对应的内容。所以一个路由要满足两个基本的条件。一个匹配用户的标识,一个是匹配成功的内容。对于react-router来说,它的路由有点不同,它不是配置型的,而是使用组件,对于路由所要满足的两个基本条件,它就是给组件定义两个属性。它提供的路由组件是Route, 对于匹配它是path属性,对于内容,则是component 属性,定义home 的路由,就可以这么写。
<Route path=’/home’, component= {home} /> // 当然,我们这里要写好Home 组件。
定义成功后,用户如果访问home, 则展示home 组件的内容。其实, 我们只是写好了一条路由,当用户访问About呢?那肯定渲染About的内容,那就要再写一条匹配路由
<Route path=’/about’, component= {About} />
如果页面中还要有其它内容访问,那么我们就要依次写好上面的路由。我们这样一条条的路由是定义好了,还需要进行控制和管理。当有户进行访问的时候,它要去查找匹配的路由,React-Router 提供了一个hashRouter, 和browserRouter组件,我们只要把这一条条的路由放到它下面的,它就会自动管理了。hashRouter 是根据hash 值的变化进行管理,browserRouter 则是根据h5 的历史管理api 进行管理。
理论知识讲的差不多了,我们实战体验一下react-router 吧。 直接使用create-react-app 创建项目,cnpm install react-router --save 就可以了。 项目就是一个简单的企业网站,它有5个部分:首页,关于我们,企业事件,联系我们,公司产品。 每一个部分占据一个页面区域,看起来是一个多页应用,其实它是一个单页应用。 对应这几个部分, 我们分别写几个组件: home, about, events, contact, products. 组件内部随便返回点内容,表示不同的页面。新建一个pages.js文件,内容如下:
import React from 'react' // 首页内容
export const Home = () => (
<section className="home">
<h1>企业网站</h1>
<p>首页内容</p>
</section>
) // 企业事件内容
export const Events = () => (
<section className="events">
<h1>企业大事件</h1>
</section>
) // 公司产品
export const Products = () => (
<section className="products">
<h1>公司产品:手机、电脑</h1>
</section>
) // 联系我们
export const Contact = () => (
<section className="contact">
<h1>联系我们</h1>
<p>公司电话:0755 - 12345678</p>
</section>
) // 关于我们
export const About = () => (
<section className="about">
<h1>公司理念</h1>
<p>公司以人为本</p>
</section>
)
组件写完了,我们就要定义路由,好让用户访问时返回正确的内容。路由的定义用到了Route 组件,它有两个属性:path和compoent. path, 路径的意思,表示用户怎么访问,component 就是很简单了,表示渲染的组件。因为有5个部分,所以要定义5条路由
<Route path='/' component={Home}/>
<Route path='/about' component={About}/>
<Route path='/contact' component={Contact}/>
<Route path='/products' component={Products}/>
<Route path='/events' component={Events}/>
路由是需要管理的,所以我们要把上面定义好的路由放到Router下面,react-router 提供了hashRouter 和brwoserRouter 组件,我们在这里使用hashRouter。不过要注意的是,无论是hashRouter 还是brwoserRouter,它都只接受一个元素,所以我们还要使用一个div把上面的5个路由包括起来放到hashRouter下面。
<Router>
<div>
<Route path='/' component={Home}/>
<Route path='/about' component={About}/>
<Route path='/contact' component={Contact}/>
<Route path='/products' component={Products}/>
<Route path='/events' component={Events}/>
</div>
</Router>
我们把整个路由配置放到什么地方呢?放到根组件下,在这里,就是放到app 组件下面, 这样,Router 就可以管理 我们整个应用的路由了。整 个app.js 文件如下:
import React from 'react'
// 引入hashRouter Route 组件
import { HashRouter, Route } from 'react-router-dom' // 引入5个组件
import { About, Contact, Home, Products, Events } from './pages'; function App() {
return (
<HashRouter>
<div>
<Route path='/' component={Home}/>
<Route path='/about' component={About}/>
<Route path='/contact' component={Contact}/>
<Route path='/products' component={Products}/>
<Route path='/events' component={Events}/>
</div>
</HashRouter>
)
} export default App
现在配置完成了, npm start 启动服务看一看效果, 看到首页内容了。
那我们怎么访问其它页面的内容呢?在介绍理论知识内容的时候说了,那就要标识请求,标识请求的地方在于浏览器的地址栏中。这时我们在地址栏的后面输入about, 显示About组件的内容,输入events, 显示event 组件的内容。但这时你会发现一个问题,无论在哪个路径下,它都用home组件的内容,这是为什么呢?原来是path匹配的问题。
地址栏中的地址和path属性值的匹配是使用的正则表达式进行匹配,所以/about 和 / 都会匹配到 /, 只要匹配成功,对应的组件就会渲染出来,所以总会有home 组件进行展示, 这肯定不是我们想要的,必须要一一对应。这时要用到一个属性exact, 只要把它加到<Route path=’/’ component = ‘home’> 上,就表示严格匹配,这时/about 就不会匹配到/, 只有/ 才能成功匹配/, 所以当/about页面时,就不会显示home 页面。home 组件路由改成如下就可以了。
<Route path='/' exact component={Home}/>
这里还会遇到一个问题, 如果用户随便输入一个路径,我们没有设置对应的路由进行匹配,怎么办?如输入hello, 页面一片空白, 用户体验肯定不好。就和服务器会返回一个404页面一样,我们肯定要写一个组件,告诉用户没有匹配成功。那就在pages.js 下面再写一个组件,
export const NotFound404 = () =>(
<div className="whoops-404">
<h1>没有页面可以匹配</h1>
</div>
)
现在就要把这个组件用路由进行管理,再写一条路由, 但path 属性要怎么写呢?因为用户任意输入,我们是不可能提前知道的,那就直接不写路径了, 不写路径,就表示这个组件可以匹配任意路径,这又会遇到另外一个问题,我们只想在没有匹配的时候,显示该组件, React-Router 提供了switch 组件来解次这个问题。我们把每一条路由用switch 组件包起来。switch 组件的作用,就像js 中switch 条件判断功能一样,它从上到下依次匹配,如果成功就会渲染组件,如果不成功,接着继续向下找,直到找到一个匹配的为止,所以没有匹配成功的路径都会到 NotFound404 组件,每一条有path属性的Route相当于一个case, 没有path的Route 则相当提供了一个default。
<HashRouter>
<div>
<Switch>
<Route path='/' exact component={Home}/>
<Route path='/about' component={About}/>
<Route path='/contact' component={Contact}/>
<Route path='/products' component={Products}/>
<Route path='/events' component={Events}/>
<Route component={NotFound404}/>
</Switch>
</div>
</HashRouter>
现在路由功能正常了,但是是通过改变地址栏来进行导航的,对于验证功能是没有什么问题的, 用户使用,问题就大了,没有人愿意手动输入地址来进行页面导航。有没有更好的办法来解决这个问题,React-Router 提供了link, navLink 组件, 它们功能是一样的,都是用于导航,只是使用的场景不一样。navLink 组件是Link 组件的一种特殊化、如果是使用文字,按钮进行导航的话,就需要高亮显示当前我们在哪个位置以进行区分,navLink 提供了一个activeClass 或activeStyle 属性,可以直接设置高亮样式。但 如果点击图片进行导航,那就不需要对图片进行高亮,那就用link.
现在我们在home 组件中增加四个link用于导航,它有一个to属性,表示到什么地方去,最基本的用法就是提供一个字符串路径,这个路径和Route中的path属性一一对应就可以了。如<Link to=’/about’>关于我们</Link>,就表示要到/about 下面。
import React from 'react'
// 引入link 组件
import { Link } from "react-router-dom";
import './pages.css'; // 首页内容
export const Home = () => (
<section className="home">
<h1>企业网站</h1>
<nav>
{/* 添加了四个导航组件Link */}
<Link to='/about'>关于我们</Link>
<Link to='/events'>企业事件</Link>
<Link to='/products'>公司产品</Link>
<Link to='/contact'>联系我们</Link>
</nav>
</section>
)
这时,我们点击不同的link 就可以进行页面导航,这时你会发现点击link, 它还是改变地址栏,和我们手动改变地址栏是一模一样的。 其实link的本质是a 标签,to属性变成了它的href属性, 打开控制台,查看element 元素就可以看到。
这时,我们想要给link 添加样式,实际上就是给a 标签添加样式。nav a 就可以了。pages.css 内容如下:
html, body, #root {
height: 100%;
}
h1 {
font-size: 3em;
color: slategray;
}
/* home 组件 */
.home {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.home > nav {
display: flex;
justify-content: space-around;
padding: 1em;
width: calc(100% - 2em);
border-top: dashed 0.5em ghostwhite;
border-bottom: dashed 0.5em ghostwhite;
background-color: slategray;
} .home > nav a {
font-size: 2em;
color: ghostwhite;
flex-basis: 200px;
} /* 其它组件 */
section.events,
section.products,
section.contact {
flex-grow:;
margin: 1em;
display: flex;
justify-content: center;
align-items: center;
}
/* 404页面 */
.whoops-404 {
position: fixed;
top:;
left:;
z-index:;
display: flex;
width: 100%;
height: 100%;
margin:;
justify-content: center;
align-items: center;
background-color: darkred;
color: ghostwhite;
font-size: 1.5em;
}
这就是react-router 最基本的用法, Link 用于导航或跳转,Route 用于定义一条一条的路由,Router 则管理路由,进行匹配。我们每次都是定义一条一条的路由,其实就是告诉Router, 当浏览器的地址栏中的地址发生变化时,哪个组件会被渲染出来。每一条路由都有两个path, component 两个属性,当浏览器地址栏中的地址,能够匹配path时,相应的component 就会显示出来。当地址是/ 时,router 会去渲染相应的home 组件。当地址是/about 时,router 会去渲染相应的Products组件。
其实在Router渲染相应组件的时候,它会向组件props属性中添加3个属性history, location, match. history和window.history对象一样,也可以用于导航,它有push, go等方法,这可以用于编程式导航. location则是浏览器地址栏对象,可以获取到当前路径什么的, match,则用表示匹配,可以获取到匹配的参数等。我们在404NotFound组件中把这三个属性打印出来。
export const NotFound404 = (props) =>(
console.log(props.location),
console.log(props.match),
console.log(props.history),
<div className="whoops-404">
<h1>没有页面可以匹配</h1>
</div>
)
React Router 4.0 基本使用的更多相关文章
- react router 4.0以上的路由应用
thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr& ...
- React Router 4.0 实现路由守卫
在使用 Vue 或者 Angular 的时候,框架提供了路由守卫功能,用来在进入某个路有前进行一些校验工作,如果校验失败,就跳转到 404 或者登陆页面,比如 Vue 中的 beforeEnter 函 ...
- 初步学习React Router 4.0
React Router 4.0 是react官方推荐的路由库.4是已经正式发布的最新版本. 初始化项目启动之后: npm run eject 弹出配置文件.自定义配置webpack 查看下pac ...
- React Router 4.0 + webpack 实现组件按需加载
网上关于React Router 4.0的按需加载文章有很多,大致的思路都一样,但是其实具体实现起来却要根据自己的实际情况来定,这里主要介绍一下我的实现方式. 主要方式是通过Route组件的rende ...
- React Router 4.0 体验
React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件.所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编 ...
- React Router V4.0学习笔记
最近在学习React Router,但是网站的教程多半还是3.X版本之前的,所以我只能在GitHub上找到React Router的官方文档在读.后来总结了一下,包括学习经验以及V3.X与V4.X的差 ...
- React Router 4.0 ---- 嵌套路由和动态路由
嵌套路由,从广义上来说,分为两种情况:一种是每个路由到的组件都有共有的内容,这时把共有的内容抽离成一个组件,变化的内容也是一个组件,两种组件组合嵌套,形成一个新的组件.另一种是子路由,路由到的组件内部 ...
- React Router 4.0中文快速入门
import React from 'react' import { BrowserRouter as Router, Route, Link } from 'react-router-dom' co ...
- 【共享单车】—— React后台管理系统开发手记:Router 4.0路由实战演练
前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录.最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star. ...
随机推荐
- 完成了Coursera的一个机器学习课程
终于完成了这个课程,从开始学习,到现在差不多过了一年的时间,中间由于一些原因耽搁了,最终还是完成了,记录一下!
- Codechef SUMCUBE Sum of Cubes 组合、三元环计数
传送门 好久没有做过图论题了-- 考虑\(k\)次方的组合意义,实际上,要求的所有方案中导出子图边数的\(k\)次方,等价于有顺序地选出其中\(k\)条边,计算它们在哪一些图中出现过,将所有方案计算出 ...
- Microsoft Artificial Intelligence Conference(2018.05.21)
时间:2018.05.21地点:北京嘉丽大酒店
- a2dp播放流程源码分析
之前分析了a2dp profile 的初始化的流程,这篇文章分析一下,音频流在bluedroid中的处理流程. 上层的音频接口是调用a2dp hal 里面的接口来进行命令以及数据的发送的. 关于控制通 ...
- EntityFramework Core并发导致显式插入主键问题
前言 之前讨论过EntityFramework Core中并发问题,按照官网所给并发冲突解决方案以为没有什么问题,但是在做单元测试时发现too young,too simple,下面我们一起来看看. ...
- OpenResty入门之使用Lua扩展Nginx
记住一点:nginx配置文件很多坑来源自你的空格少了或多了. 1.Centos下载安装 如果你的系统是 Centos 或 RedHat 可以使用以下命令: yum install readline-d ...
- 读写分离子系统 - C# SQL分发子系统(目前只支持ADO.NET)
这次介绍的这个框架只适用于中小项目,并且各个读写数据库结构是一致的情况,还要并且是写入数据库只有1台情况. 我们来看看这个子系统适用的场景: 我们来看这个子系统的配置文件: <?xml vers ...
- docker安装并修改Nginx镜像
1.安装nginx镜像,命令:docker pull nginx 2.创建nginx容器,并启动,命令:docker run --name webserver -d -p 192.168.51.227 ...
- Appium+Python3+iOS定位元素
前言: 最近在做IOS自动化测试,IOS的Appium环境都配置OK,执行起来真的慢,慢到怀疑人生,那么今天就来总结一下IOS定位方式和各个定位方式的速度排序. 据我观察,按查找元素的顺序速度,从快到 ...
- 03-HTML之body标签
body标签 HTML标签按作用主要分为两类:字体标签和排版标签 HTML标签按级别主要分为两类:文本级标签和容器级标签 文本级标签:p.span.a.b.i.u.em.文本标签里只能放文字.图片.表 ...