1. 后端路由与前端路由
多页面应用和后端路由
在传统的Web应用中,浏览器根据地址栏的URL向服务器发送一个HTTP请求,服务器根据URL返回一个HTML页面。这种情况下,一个URL对应一个HTML页面,一个Web应用包含很多HTML页面,这样的应用就是 多页面应用;在多页面应用中,页面路由的控制由服务器端负责,这种路由方式称为 后端路由。
单页面应用和前端路由
URL的变化可以引起页面内容的变化,但不会向服务器发送新的请求,页面的内容也会发生变化,但这只是逻辑上的页面变化,无论URL如何变化,对应的HTML文件都是同一个,这样叫做 单页面应用. 在单页面应用中,URL发生变化并不会向服务器发送新的请求,所以“逻辑页面”(这个名称用来和真实的HTML页面区分)的路由只能由前端负责,这种路由方式称为 前端路由。
React Router就是一种前端路由的实现方式。通过使用React Router可以让Web应用根据不同的URL渲染不同的组件,这样的组件渲染方式可以解决更加复杂的业务场景。例如,当URL的pathname为/list时,页面会渲染一个列表组件,当点击列表中的一项时,pathname更改为/item/:id(id为参数),旧的列表组件会被卸载,取而代之的是一个新的单一项的详情组件。
2. 安装路由
npm install react-router-dom
React Router包含3个库:react-router、react-router-dom和react-router-native。
react-router提供最基本的路由功能,实际使用时,我们不会直接安装react-router.
而是根据应用运行的环境选择安装react-router-dom(在浏览器中使用)或react-router-native(在react-native中使用)。
react-router-dom和react-router-native都依赖于react-router,所以在安装时,react-router也会自动安装。
所以我们只需要安装 react-router-dom
3. 引入路由
引入路由
// 哈希模式
import {HashRouter as Router, Link, Route} from 'react-router-dom'
//或者
// history模式
import {BrowserRouter as Router, Link, Route} from 'react-router-dom'
// ReactRouter三大组件
// Router 所有路由组件的根组件, 包裹路由规则的最外层容器
// Route 路由规则匹配组件, 显示当前规则对应的组件
// Link 路由跳转组件
4. HashRouter和BrowserRouter
Router可以理解成路由器,一个应用中只需要一个Router实例, React Router中的其他组件必须作为Router组件的后代组件使用。但Router中只能有唯一的一个子元素
Router会创建一个history对象,history用来跟踪URL,当URL发生变化时,Router的后代组件会重新渲染。React Router中提供的其他组件可以通过context获取history对象
BrowserRouter使用HTML 5的history API(pushState、replaceState等)实现应用的UI和URL的同步
BrowserRouter创建的URL形式如下:http://example.com/some/path
使用BrowserRouter时,一般还需要对服务器进行配置,让服务器能正确地处理所有可能的URL。例如,当浏览器发送http://example.com/some/path
和http://example.com/some/path2
两个请求时,服务器需要能返回正确的HTML页面(也就是单页面应用中唯一的HTML页面)
HashRouter使用URL的hash实现应用的UI和URL的同步。
HashRouter创建的URL形式如下:http://example.com/#/some/path
使用HashRouter则不存在这个问题,因为hash部分的内容会被服务器自动忽略,真正有效的信息是hash前面的部分,而对于单页面应用来说,这部分内容是固定的
5. Route
Route是匹配组件, 常用的属性有path和component.
Route的exact和strict修饰符
exact 精确匹配 默认为false,如果为true时,需要和路由相同时才能匹配。
false 路由:'/Home' url '/Home' 和 '/Home/myPage' 都会匹配
true 路由:'/Home' 只有url '/Home'才匹配, url '/Home/myPage' 不匹配
strict 斜杠敏感 默认为false,如果为true时,url对斜杠敏感
false url '/Home' 和 url '/Home/' 视为相同的url
true url '/Home' 和 url '/Home/' 视为不相同的url
6. Link
Link是跳转组件, 常用的属性是 to
to属性值可是字符串
也可以是对象: 这个对象包含 pathname、search、hash、state四个属性
例如:
let toArgs = {
// 跳转的路径
pathname: '/User',
// get的入参
search: '?user=admin',
// hash的值
hash: '#abc',
// 组件的值
state: {fromHome: true}
}
组件中的 this.props.location
存放着这个入参
在组件中查看这个入参:
this.props.location.state.fromHome;
7. switch
当 Router中的Route有多个符合匹配条件时, 如果不添加switch, 所有匹配的组件都会渲染
当 这些Route被 switch包裹时, 当第一个符合匹配条件的组件渲染后, 不再向下匹配. (保证只显示第一个匹配的组件)
8. history
路由页面跳转
history.push(path,[state])
history.replace(path,[state])
区别:
push是把新页面放入栈中, 保留上一个页面的历史记录, 这样返回还可以回到上一个页面
replace是把新页面替换上一个页面在栈中的历史记录, 这样返回的时候会回到上上个页面
现在有三个页面 a->b->c
b跳转c的时候, 如果使用push到c页面,在c页面点击返回回到b页面
b跳转c的时候, 如果使用replace到c页面,在c页面点击返回回到a页面
// 向前或向后跳转n个页面, 正数为前进, 负数为后退
this.props.history.go(n)
// 前进
this.props.history.go(1);
//或者
this.props.history.goForward();
// 回退
this.props.history.go(-1);
//或者
this.props.history.goBack();
9. 动态路由
Route这样写 /path/:动态参数 如:
Link这样写 /path/具体的参数 如:
用户
生产的url是 #/User/admin
组件的this.props.match.params
存放这个动态参数
在组件中查看这个动态参数
this.props.match.params.user;
10. Redirect重定向
待补充...
11. 组件被加入路由后, 组件的this.props新增属性
this.props.history
this.props.history提供了push, replace, go, goBack, goForward等方法
// this.props.history.go(n)
// 向前或向后跳转n个页面, 正数为前进, 负数为后退
// 前进
this.props.history.go(1);
this.props.history.goForward();
// 回退
this.props.history.go(-1);
this.props.history.goBack();
this.props.location
this.props.location存放的是Link to属性传入的对象,包括pathname、search、hash、state四个属性
let toArgs = {
// 跳转的路径
pathname: '/User',
// get的入参
search: '?user=admin',
// hash的值
hash: '#abc',
// 组件的值
state: {fromHome: true}
}
登录
// 组件中的 this.props.location 存放着这个入参
// 在组件中查看这个入参
this.props.location.state.fromHome;
this.props.match
this.props.match.params存放着动态路由的动态参数
// Route这样写 /path/:动态参数 如:
// Link这样写 /path/具体的参数 如:
用户
// 访问这个属性:
this.props.match.params.user;
11. window.location
页面刷新时, 如果想要访问到当前页面的哈希路径, 以此来作为判断条件做一些预处理, 在react的生命周期函数UNSAFE_componentWillMount执行时, props属性还没有被注入数据的情况, 可以通过window.location来访问到hash路径
UNSAFE_componentWillMount(){
/* 每次刷新页面时,可以通过window.location获取到当前的hash路径, 以此来获取一下当前页等信息.
然后定位对应的位置等操作. 因为页面刚刷新, 在willMount的时候我们还无法访问props.
*/
console.log('页面刷新时会调用这个方法. 来查看一下刷新时的hash路由');
//可以看到这时候props还没有数据, 如果想拿到哈希路径, 就需要访问window.location
console.log('this.props',this.props);
console.log(window.location.hash);
console.log(window.location.hash.split('/'));
console.log(window.location.hash.split('/')[1]);
}