深入理解react-router 路由的实现原理


Posted in Javascript onSeptember 26, 2018

React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步。本文从两个方便来解析 react-router 实现原理。一:介绍 react-router 的依赖库history;二:使用 history 库,实现一个简单的 react-router 路由。

history 介绍

history 是一个 JavaScript 库,可让您在 JavaScript 运行的任何地方轻松管理会话历史记录。history 抽象出各种环境中的差异,并提供最小的 API ,使您可以管理历史堆栈,导航,确认导航以及在会话之间保持状态。

history 有三种实现方式:

1、BrowserHistory:用于支持 HTML5 历史记录 API 的现代 Web 浏览器(请参阅跨浏览器兼容性)
2、HashHistory:用于旧版Web浏览器
3、MemoryHistory:用作参考实现,也可用于非 DOM 环境,如 React Native 或测试

三种实现方法,都是创建了一个 history 对象,这里主要讲下前面两种:

const history = {
 length: globalHistory.length, 
 action: "POP", 
 location: initialLocation,
 createHref,
 push, // 改变location
 replace,
 go,
 goBack,
 goForward,
 block,
 listen //监听路由变化
};

1.页面跳转实现

BrowserHistory:pushState、replaceState;

HashHistory:location.hash、location.replace

function push(){
 createKey(); // 创建location的key,用于唯一标示该location,是随机生成的
 if(BrowserHistory){
 globalHistory.pushState({ key, state }, null, href);
 }else if(HashHistory){
 window.location.hash = path;
 }
 //上报listener 更新state ...
}
function replace(){
 createKey(); // 创建location的key,用于唯一标示该location,是随机生成的
 if(BrowserHistory){
 globalHistory.replaceState({ key, state }, null, href); 
 }else if(HashHistory){
 window.location.replace(window.location.href.slice(0, hashIndex >= 0 ? hashIndex : 0) + "#" path);
 } 
 //上报listener 更新state ... 
}

2.浏览器回退

BrowserHistory:popstate;

HashHistory:hashchang;

if(BrowserHistory){
 window.addEventListener("popstate", routerChange);
}else if(HashHistory){
 window.addEventListener("hashchange", routerChange);
}
function routerChange(){
 const location = getDOMLocation(); //获取location
 //路由切换
 transitionManager.confirmTransitionTo(location,callback=()=>{
 //上报listener
 transitionManager.notifyListeners();
 });
}

通过 history 实现简单 react-router

import { Component } from 'react';
import createHistory from 'history/createHashHistory';
const history = createHistory(); //创建 history 对象
/**
 * 配置路由表
 * @type {{"/": string}}
 */
const router = {
 '/': 'page/home/index',
 '/my': 'page/my/index'
}
export default class Router extends Component {
 state = { page: null }

 async route(location) {
 let pathname = location.pathname;
 let pagePath = router[pathname];
 // 加 ./的原因 https://webpack.docschina.org/api/module-methods#import-
 const Page = await import(`./${pagePath}`); //获取路由对应的ui
 //设置ui
 this.setState({ 
  Page: Page.default 
 });
 }

 initListener(){
 //监听路由切换
 history.listen((location, action) => {
  //切换路由后,更新ui
  this.route(location);
 });
 }

 componentDidMount() {
 this.route(history.location);
 this.initListener();
 }

 render() {
 const { Page } = this.state;
 return Page && <Page {...this.props} />;
 }
}

目前react-router在项目中已有大量实践,其优点可以总结如下:

风格: 与React融为一体,专为react量身打造,编码风格与react保持一致,例如路由的配置可以通过component来实现

简单: 不需要手工维护路由state,使代码变得简单

强大: 强大的路由管理机制,体现在如下方面

  • 路由配置: 可以通过组件、配置对象来进行路由的配置
  • 路由切换: 可以通过<Link> Redirect进行路由的切换
  • 路由加载: 可以同步记载,也可以异步加载,这样就可以实现按需加载

使用方式: 不仅可以在浏览器端的使用,而且可以在服务器端的使用

当然react-router的缺点就是API不太稳定,在升级版本的时候需要进行代码变动。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
accesskey 提交
Jun 26 Javascript
node.js中的fs.chown方法使用说明
Dec 16 Javascript
删除javascript所创建子节点的方法
May 21 Javascript
js实现向右横向滑出的二级菜单效果
Aug 27 Javascript
JS利用cookie记忆当前位置的防刷新导航效果
Oct 15 Javascript
Easyui Treegrid改变默认图标的方法
Apr 29 Javascript
js实现上传图片及时预览
May 07 Javascript
集合Bootstrap自定义confirm提示效果
Sep 19 Javascript
ES6解构赋值的功能与用途实例分析
Oct 31 Javascript
详解如何在Angular优雅编写HTTP请求
Dec 05 Javascript
javascript实现点击产生随机图形
Jan 25 Javascript
vue使用localStorage持久性存储实现评论列表
Apr 14 Vue.js
node.js使用redis储存session的方法
Sep 26 #Javascript
详解Axios统一错误处理与后置
Sep 26 #Javascript
Vue监听一个数组id是否与另一个数组id相同的方法
Sep 26 #Javascript
vue 循环加载数据并获取第一条记录的方法
Sep 26 #Javascript
基于vue v-for 多层循环嵌套获取行数的方法
Sep 26 #Javascript
VUE v-for循环中每个item节点动态绑定不同函数的实例
Sep 26 #Javascript
原生JS实现简单的无缝自动轮播效果
Sep 26 #Javascript
You might like
Extended CHM PHP 语法手册之 DIY
2006/10/09 PHP
php setcookie(name, value, expires, path, domain, secure) 参数详解
2013/06/28 PHP
php 启动报错如何解决
2014/01/17 PHP
PHP上传Excel文件导入数据到MySQL数据库示例
2016/10/25 PHP
node.js中的fs.chown方法使用说明
2014/12/16 Javascript
41个Web开发者必须收藏的JavaScript实用技巧
2016/07/22 Javascript
BootStrap无限级分类(无限极分类封装版)
2016/08/26 Javascript
AngularJS基于ui-route实现深层路由的方法【路由嵌套】
2016/12/14 Javascript
详解微信小程序开发之城市选择器 城市切换
2017/01/17 Javascript
layui.js实现的表单验证功能示例
2017/11/15 Javascript
Element-ui tree组件自定义节点使用方法代码详解
2018/09/17 Javascript
JS实现水平遍历和嵌套递归操作示例
2019/08/15 Javascript
python基于mysql实现的简单队列以及跨进程锁实例详解
2014/07/07 Python
Python编码爬坑指南(必看)
2016/06/10 Python
Linux上安装Python的PIL和Pillow库处理图片的实例教程
2016/06/23 Python
[原创]windows下Anaconda的安装与配置正解(Anaconda入门教程)
2018/04/05 Python
python2.7 安装pip的方法步骤(管用)
2019/05/05 Python
Python 3.6打包成EXE可执行程序的实现
2019/10/18 Python
为什么说python适合写爬虫
2020/06/11 Python
Python 爬虫的原理
2020/07/30 Python
jupyter notebook快速入门及使用详解
2020/11/13 Python
英国女士和男士时尚服装网上购物:Top Labels Online
2018/03/25 全球购物
Fanatics英国官网:美国体育电商
2018/11/06 全球购物
Dr.Jart+美国官网:韩国药妆品牌
2019/01/18 全球购物
德国、奥地利和瑞士最大的旅行和度假门户网站:HolidayCheck
2019/11/14 全球购物
Belstaff英国官方在线商店:Belstaff.co.uk
2021/02/09 全球购物
华为python面试题
2016/05/03 面试题
有个性的自我评价范文
2013/11/15 职场文书
司机检讨书
2014/02/13 职场文书
党建示范点实施方案
2014/03/12 职场文书
2015年女生节活动总结
2015/02/27 职场文书
2015员工年度考核评语
2015/03/25 职场文书
考勤制度通知
2015/04/25 职场文书
交通事故起诉书
2015/05/19 职场文书
Vue和Flask通信的实现
2021/05/19 Vue.js
解决numpy和torch数据类型转化的问题
2021/05/23 Python