前置知识
SPA应用
在了解Router之前,我们需要知道的前置知识是SPA应用,它的全称为single Page Application,全名为单页面应用,即基本所有功能都在一个页面完成。
与它做对比的就是传统的a标签页面,由于传统的a标签页面每次点击都会给服务器发送指令,通过服务器返回让用户界面进行资源加载,这种方式受网速影响较大,且对于服务器来说大量的数据传输转发都会造成一定压力,种种因素造成用户的体验感不是很好。
单页面应用的诞生对于上面的问题有着明显的改善,比如说我们把一个页面都一次性发送给用户,然后随着用户的点击来切换不同的内容,对于用户来说刷新的速度非常快。
SPA原理
这里只总体介绍一下,如果对原理更感兴趣,可以参考我写的这篇深入理解前端路由
hash模式
SPA一开始是使用hashChange事件来完成的,基本原理就是通过url中hash的改变来响应不同的页面,实际上就是通过获取#后面的字符,通过hash与dom的映射关系来让不同的页面展示出来,这叫hash模式
history模式
由于HTML5出来后新增了pushState事件,我们可以往history上使用这个,就可以把url给改掉而不刷新页面,这就可以拿到对应的路径,再通过path和dom的映射关系把不同的页面展示出来,这叫history模式
memory模式
上面两种都是通过对url栏的修改形成与页面之间的对应关系来实现的,memory模式是使用localstorage把字符存进去,这个跟url栏就没有一点关系了,适合只有一个url的情况下使用。
一般我们开发的时候会使用hash模式,生产模式会使用history模式。因为history模式对seo更友好,百度爬虫会收录/之后的东西,而忽略#后面的东西。
hash模式适合开发的原因是#不会向服务器发送请求,都是浏览器自己完成,而/的方式如果调试时刷新了页面,就会向后端发送请求,就会需要后端首先配置好response内容。
Router
Router翻译过来就是路由器,它的作用就是帮助分发请求,实现请求与页面相对应的展示效果。
Router的目的就是帮助前端人员更好地规划路由展示效果,开发SPA应用。
React-Router是React团队研发出来协助React程序员开发项目时,提前写好API方便使用的一个库,我们目前就要学习如何使用它。
Router基本使用
安装
yarn add react-router-dom
基本概念
目前的版本中React-Router提供三大组件
- Router是所有路由组件共用的底层接口组件,它是路由规则制定的最外层的容器。你可以叫他为路由器
- Route路由规则匹配,并显示当前的规则对应的组件。你可以叫他路由匹配器
- Link路由跳转的组件,你可以叫他导航
其中Router组件针对不同的功能和平台有以下子组件
<BrowserRouter>浏览器的路由组件<HashRouter>URL格式为Hash路由组件<MemoryRouter>内存路由组件<NativeRouter>Native的路由组件<StaticRouter>地址不改变的静态路由组件 Router就是个容器,所有路由操作都要在Router里面,
Route是用来做路由规则的,它定义的是路径和显示组件之间的对应关系
Link就是a标签,实现声明式的跳转
下面通过实例来理解,请手动使用create-react-app打好手脚架,再把我的代码放入App.js文件中。
创建一个Router组件
import { BrowserRouter as Router, Link, Route } from "react-router-dom";
import "./App.css";
const Home = () => (
<div>
<h2>Home</h2>
</div>
);
const About = () => (
<div>
<h2>About</h2>
</div>
);
const Product = () => (
<div>
<h2>Product</h2>
</div>
);
function App() {
return (
<Router>
<div className="App">
<Link to="/">Home</Link>
<hr />
<Link to="/About">About</Link>
<hr />
<Link to="/Product">Product</Link>
<hr />
<Route path="/" exact component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/product" component={Product}></Route>
</div>
</Router>
);
}
export default App;
说明
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
1、上面的引入方式是把BrowserRouter、Route、Link引入进来,然后给BrowserRouter取一个别名Router,这样有个好处,以后我如果想换掉BrowserRouter只需要一行代码。
2、可以看到我在App函数中,使用Router将所有内容都包裹起来了,然后在<Route>标签内写入path='/' exact component={Home}意思是当我的路径是/时,渲染Home组件,exact是准确、精确的意思,表示准确匹配,它是Route的属性。
如果你使用yarn start来查看页面,就会看到这样的画面,试着点点看
好了,你已经初步了解Router了。下面我们来了解一下主要的API
Router组件
上面我们说原理的时候说过,有使用hash的Hash模式,有使用pushState的history模式,React自然也给了我们选择,分别是对应history模式的BrowserRouter和对应Hash模式的HashRouter。
这两个都是顶级组件,直接定义使用什么模式,反正开发用Hash、生产用history,我想你已经会选了。
属性
- basename: 字符串类型,路由器的默认根路径
- forceRefresh: 布尔类型,在导航的过程中整个页面是否刷新
- getUserConfirmation: 函数类型,当导航需要确认时执行的函数。默认是:window.confirm
- keyLength: 数字类型location.key 的长度。默认是 6
basename
基准url的名称,比如说我们有个二级子目录admin,我需要把应用放到这个模块下,如果不带这个basename,那我有可能写三四遍link to='/admin/xxx',现在我只需要写一遍,就像这样
<Router basename="/admin">
<div className="App">
<Link to="/">Home</Link>
<hr />
<Link to="/About">About</Link>
<hr />
<Link to="/Product">Product</Link>
<hr />
<Route path="/" exact component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/product" component={Product}></Route>
forceRefresh:bool
当设置为true时,在导航的过程中整个页面会刷新。
Link组件
Link组件就是解析前的a标签
to属性
通过to属性来指明目标,to属性可以直接指明一个字符串,也可以指明一个对象表示我要跳转这个路径或者地址
<Link
to={{
pathname: "/about",
search: "?key=name",
hash: "#hash",
state: { fromDashboard: true },
}}
>
About
</Link>
replace:bool
默认为false,当设置为 true的时候,会替换掉历史记录的原地址。
NavLink组件
NavLink是一个特殊版本的Link,可以使用activeClassName来设置Link被选中时被附加的class,使用activeStyle来配置被选中时应用的样式。此外,还有一个exact属性,此属性要求location完全匹配才会附加class和style。这里说的匹配是指地址栏中的URl和这个Link的to指定的location相匹配。
属性
- to:跟Link组件一样
- exact:精准匹配,所有单单指向
/的都要用这个,不然会匹配到一切带/的路径,例如/a,这样就不准确。 - activeClassName:选中后添加class属性
- activeStyle:选中后添加style
<NavLink activeClassName="selected" to="/About">
About
</NavLink>
上面的代码,如果用户选中这个连接,那么就会加上class属性。
Route组件
Route组件是用来定路径与组件的对应关系的,是react-Router中最重要的组件。
先来说说Route的三种渲染方式
1、component:渲染组件
2、render:这里写function,这个可以用来加一些逻辑,Route会渲染function的返回值,实际上就是允许你写组件
<Route
path="/"
exact
render={(props) => {
console.log(props)
if (1 > 2) {
return <Home />;
}
}}
></Route>
注意这里的props,会记录history、location等参数
3、children:跟render类似语法,但是多了一个参数match,并且不管怎样都会渲染
switch组件
switch组件用来渲染第一个匹配成功的组件
<Route path="/about" component={About}></Route>
<Route path="/product" component={Product}></Route>
<Route path="/" component={Home}></Route>
上面代码,但我的path为/about的时候,会同时渲染出Home组件跟About组件
是因为在模糊匹配下,
/about这个路径也可以匹配到/,所以才造成上述问题,那么当我用了switch的时候,就只会渲染第一个匹配成功的。
< route path = "/" > 总是与 URL 匹配。正因为如此,我们通常将这个 < route > 放在 < switch > 中的最后
小tips:这里最好经常在
path="/"的Route内加exact属性,否则有可能会出现问题哦
Redrict组件
重定向组件,就是比如你输入/abc的时候给你切换到/下,一般跟render一起用
<Route path="/abc" render={() => {
return <Redirect to="/" />;
}}/>
上面的代码的意思是当path为/abc的时候,重新定向到/。
Prompt组件
当用户离开当前页面前做出一些提示。
写在最后
由于React的文档写得实在阅读成本很高,如果抛开需求硬学API的话效率非常低,所以主张在项目中解决这些问题,目前对于基本使用,我们只需要知道上面得一些基础API即可,如果我后期发现更多好玩常用的的特性,也会随时更新在这篇博客上。