vue-router 源码实现前端路由的两种方式


Posted in Javascript onJuly 02, 2018

在学习 vue-router 的代码之前,先来简单了解一下前端路由。

前端路由主要有两种实现方法:

  • Hash 路由
  • History 路由

先来看看这两种方法的实现原理。

接着我们将用它们来简单实现一个自己的前端路由。

前端路由

Hash 路由

url 的 hash 是以 # 开头,原本是用来作为锚点,从而定位到页面的特定区域。当 hash 改变时,页面不会因此刷新,浏览器也不会向服务器发送请求。

http://www.xxx.com/#/home

同时, hash 改变时,并会触发相应的 hashchange 事件。所以,hash 很适合被用来做前端路由。当 hash 路由发生了跳转,便会触发 hashchange 回调,回调里可以实现页面更新的操作,从而达到跳转页面的效果。

window.addEventListener('hashchange', function () {
 console.log('render');
});

History 路由

HTML5 规范中提供了 history.pushStatehistory.replaceState 来进行路由控制。通过这两个方法,可以实现改变 url 且不向服务器发送请求。同时不会像 hash 有一个 # ,更加的美观。但是 History 路由需要服务器的支持,并且需将所有的路由重定向到根页面。

History 路由的改变不会去触发某个事件,所以我们需要去考虑如何触发路由更新后的回调。

有以下两种方式会改变 url:

  • 调用 history.pushState 或 history.replaceState;
  • 点击浏览器的前进与后退。

第一个方式可以封装一个方法,在调用 pushState(replaceState)后再调用回调。

function push (url) {
 window.history.pushState({}, null, url);
 handleHref();
}

function handleHref () {
 console.log('render');
}

第二个方式,浏览器的前进与后退会触发 popstate 事件。

window.addEventListener('popstate', handleHref);

路由实现

我们通过 <a> 标签来进行切换路由,通过一个 <div> 标签来装载各路由对应的页面内容。

参考 vue-router 的调用,我们会这么地调用一个 Router ,将路由与对应组件作为参数传入:

const router = new Router([
 {
  path: '/',
  component: 'home'
 },
 {
  path: '/book',
  component: 'book'
 },
 {
  path: '/movie',
  component: 'movie'
 }
]);

数组里是各路由对应的要显示的内容,接下来就来开始实现这个 Router

Hash 路由实现

Hash 路由 <a> 标签都需要带上 #

<div>
 <a href="#/" rel="external nofollow" >home</a>
 <a href="#/book" rel="external nofollow" >book</a>
 <a href="#/movie" rel="external nofollow" >movie</a>
  
 <div id="content"></div>
</div>

Router 的代码实现如下:

class Router {
 constructor (options) {
  this.routes = {};
  
  this.init();
  
  // 遍历,绑定视图更新
  options.forEach(item => {
   this.route(item.path, () => {
   	document.getElementById('content').innerHTML = item.component;
   });
  });
 }
 
 // 绑定监听事件
 init () {
  window.addEventListener('load', this.updateView.bind(this), false);
  window.addEventListener('hashchange', this.updateView.bind(this), false);
 }
 
 // 更新试图
 updateView () {
  const currentUrl = window.location.hash.slice(1) || '/';
  this.routes[currentUrl] && this.routes[currentUrl]();
 }
 
 // 将路由与回调函数关联
 route (path, cb) {
  this.routes[path] = cb;
 }
}

实现效果如下:

vue-router 源码实现前端路由的两种方式 

History 路由实现

History 路由需要服务器的支持,可以点击这里 的代码参考。

<div>
 <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/" rel="external nofollow" >home</a>
 <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/book" rel="external nofollow" >book</a>
 <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/movie" rel="external nofollow" >movie</a>
  
 <div id="content"></div>
</div>

Router 的代码实现如下:

class Router {
 constructor (options) {
  this.routes = {};

  this.init();
  this.bindEvent();

  // 遍历,绑定视图更新
  options.forEach(item => {
   this.route(item.path, () => {
    document.getElementById('content').innerHTML = item.component;
   });
  });
 }

 // 绑定点击事件
 bindEvent () {
  const _this = this;
  const links = document.getElementsByTagName('a');

  [].forEach.call(links, link => {
   link.addEventListener('click', function () {
    const url = this.getAttribute('data-href');
    _this.push(url);
   });
  });
 }

 // 绑定监听事件
 init () {
  window.addEventListener('load', this.updateView.bind(this), false);
  window.addEventListener('popstate', this.updateView.bind(this), false);
 }

 push (url) {
  window.history.pushState({}, null, url);
  this.updateView();
 }

 // 更新试图
 updateView () {
  const currentUrl = window.location.pathname || '/';
  this.routes[currentUrl] && this.routes[currentUrl]();
 }

 // 将路由与回调函数关联
 route (path, cb) {
  this.routes[path] = cb;
 }
}

实现效果如下:

vue-router 源码实现前端路由的两种方式

最后

前端路由实现方式有两种,分别是:

  1. Hash 路由
  2. History 路由

原理都是修改 url 的同时不刷新页面,不向服务器发送请求,通过监听特殊的事件来更新页面。

以上实现全部源码参考这里。

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

Javascript 相关文章推荐
『jQuery』取指定url格式及分割函数应用
Apr 22 Javascript
jquery select多选框的左右移动 具体实现代码
Jul 03 Javascript
jquery高级编程的最佳实践详解
Mar 23 Javascript
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
Sep 17 Javascript
基于Bootstrap+jQuery.validate实现Form表单验证
Dec 16 Javascript
JavaScript判断表单提交时哪个radio按钮被选中的方法
Mar 21 Javascript
jQuery对象与DOM对象转换方法详解
May 10 Javascript
Angular.js中$apply()和$digest()的深入理解
Oct 13 Javascript
原生js实现密码输入框值的显示隐藏
Jul 17 Javascript
js实现导航跟随效果
Nov 17 Javascript
vue封装可复用组件confirm,并绑定在vue原型上的示例
Oct 31 Javascript
使用vue打包进行云服务器上传的问题
Mar 02 Javascript
React Native基础入门之调试React Native应用的一小步
Jul 02 #Javascript
vue-router 源码之实现一个简单的 vue-router
Jul 02 #Javascript
JavaScript设计模式之单例模式简单实例教程
Jul 02 #Javascript
JavaScript设计模式之建造者模式实例教程
Jul 02 #Javascript
JS实现的JSON序列化操作简单示例
Jul 02 #Javascript
JS内部事件机制之单线程原理
Jul 02 #Javascript
JS将网址url转化为JSON格式的方法
Jul 02 #Javascript
You might like
PHP测试程序运行时间的类
2012/02/05 PHP
11个PHPer必须要了解的编程规范
2014/09/22 PHP
php实现计数器方法小结
2015/01/05 PHP
php插入mysql数据返回id的方法
2018/05/31 PHP
YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例
2020/03/18 PHP
雄兵连第三季海报曝光,艾妮熙德成主角,蔷薇新造型
2021/03/09 国漫
基于json的jquery地区联动效果代码
2011/07/06 Javascript
jquery实现漂浮在网页右侧的qq在线客服插件示例
2013/05/13 Javascript
flash遮住div问题的正确解决方法
2014/02/27 Javascript
仿淘宝TAB切换搜索框搜索切换的相关内容
2014/09/21 Javascript
jQuery实现视频作为全屏幕背景
2014/12/18 Javascript
JS实现窗口加载时模拟鼠标移动的方法
2015/06/03 Javascript
jquery实现点击向下展开菜单项(伸缩导航)效果
2015/08/22 Javascript
Nodejs进阶:如何将图片转成datauri嵌入到网页中去实例
2016/11/21 NodeJs
JS作用域闭包、预解释和this关键字综合实例解析
2016/12/16 Javascript
如何写好你的JavaScript【推荐】
2017/03/02 Javascript
干货!教大家如何选择Vue和React
2017/03/13 Javascript
微信小程序实现红包功能(后端PHP实现逻辑)
2018/07/11 Javascript
利用vue重构有赞商城的思路以及总结整理
2019/02/21 Javascript
CountUp.js数字滚动插件使用方法详解
2019/10/17 Javascript
小程序如何写动态标签的实现方法
2020/02/05 Javascript
解决vue-router路由拦截造成死循环问题
2020/08/05 Javascript
JavaScript 生成唯一ID的几种方式
2021/02/19 Javascript
Python模拟用户登录验证
2017/09/11 Python
Python实现K折交叉验证法的方法步骤
2019/07/11 Python
python识别文字(基于tesseract)代码实例
2019/08/24 Python
python 使用事件对象asyncio.Event来同步协程的操作
2020/05/04 Python
python爬虫中的url下载器用法详解
2020/11/30 Python
用 Django 开发一个 Python Web API的方法步骤
2020/12/03 Python
利用Bootstrap实现漂亮简洁的CSS3价格表实例源码
2017/03/02 HTML / CSS
Soft Cotton捷克:来自爱琴海棉花的浴袍
2017/02/01 全球购物
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
初中三好学生自我鉴定
2014/04/07 职场文书
美术教师求职信范文
2015/03/20 职场文书
CocosCreator入门教程之网络通信
2021/04/16 Javascript
python实战之用emoji表情生成文字
2021/05/08 Python