内容简介:在单页应用如此流行的今天,曾经令人惊叹的前端路由已经成为各大框架的基础标配,每个框架都提供了强大的路由功能,导致路由实现变的复杂。想要搞懂路由内部实现还是有些困难的,但是如果只想了解路由实现基本原理还是比较简单的。本文针对前端路由主流的实现方式 hash 和 history,提供了原生JS/React/Vue 共计六个版本供参考,每个版本的实现代码约 25~40 行左右(含空行)。路由的概念来源于服务端,在服务端中路由描述的是在
在单页应用如此流行的今天,曾经令人惊叹的前端路由已经成为各大框架的基础标配,每个框架都提供了强大的路由功能,导致路由实现变的复杂。想要搞懂路由内部实现还是有些困难的,但是如果只想了解路由实现基本原理还是比较简单的。本文针对前端路由主流的实现方式 hash 和 history,提供了原生JS/React/Vue 共计六个版本供参考,每个版本的实现代码约 25~40 行左右(含空行)。
什么是前端路由?
路由的概念来源于服务端,在服务端中路由描述的是 URL
与处理函数之间的映射关系。
在 Web
前端单页应用 SPA(SinglePageApplication)
中,路由描述的是 URL
与 UI
之间的映射关系,这种映射是单向的,即 URL
变化引起 UI
更新(无需刷新页面)。
如何实现前端路由?
要实现前端路由,需要解决两个核心:
-
如何改变
URL
却不引起页面刷新? -
如何检测
URL
变化了?
下面分别使用 hash
和 history
两种实现方式回答上面的两个核心问题。
hash 实现
-
hash
是URL
中hash(#)
及后面的那部分,常用作锚点在页面内进行导航,改变URL
中的hash
部分不会引起页面刷新 -
通过
hashchange
事件监听URL
的变化,改变URL
的方式只有这几种:通过浏览器前进后退改变URL
、通过<a>
标签改变URL
、通过window.location
改变URL
,这几种情况改变URL
都会触发hashchange
事件
history实现
-
history
提供了pushState
和replaceState
两个方法,这两个方法改变URL
的path
部分不会引起页面刷新 -
history
提供类似hashchange
事件的popstate
事件,但popstate
事件有些不同:通过浏览器前进后退改变URL
时会触发popstate
事件,通过pushState/replaceState
或<a>
标签改变URL
不会触发popstate
事件。好在我们可以拦截pushState/replaceState
的调用和<a>
标签的点击事件来检测URL
变化,所以监听URL
变化可以实现,只是没有 hashchange 那么方便。
原生JS版前端路由实现
基于上节讨论的两种实现方式,分别实现 hash
版本和 history
版本的路由,示例使用原生 HTML/JS
实现,不依赖任何框架。
基于 hash 实现
运行效果:
HTML
部分:
JavaScript
部分:
基于 history
实现
运行效果:
HTML
部分:
JavaScript
部分:
React 版前端路由实现
基于 hash 实现
运行效果:
使用方式和react-router类似:
BrowserRouter 实现
Route
实现
基于 history
实现
运行效果:
使用方式和 react-router
类似:
HistoryRouter
实现
Route
实现
Link
实现
Vue 版本前端路由实现
基于 hash 实现
运行效果:
使用方式和 vue-router 类似(vue-router 通过插件机制注入路由,但是这样隐藏了实现细节,为了保持代码直观,这里没有使用 Vue 插件封装):
router-view 实现
router-link
实现
基于 history
实现
运行效果:
使用方式和 vue-router
类似:
router-view
实现:
router-link
实现
小结
前端路由的核心实现原理很简单,但是结合具体框架后,框架增加了很多特性,如动态路由、路由参数、路由动画等等,这些导致路由实现变的复杂。本文去粗取精只针对前端路由最核心部分的实现进行分析,并基于 hash
和 history
两种模式,分别提供原生 JS/React/Vue
三种实现,共计六个实现版本供参考,希望对你有所帮助。
作者:whinc 欢迎关注作者的github 原文:https://github.com/whinc/web-router-principle
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。