关于vue-router路径计算问题


Posted in Javascript onMay 10, 2017

昨天刚刚发表了一个前端跨域新方案尝试,今天在开发中就遇到的了问题。

起因

前端使用的是vue-router组件的history模式,但是由于我们的整个页面都是从static(静态资源站)load过来的,所以其他页面自然也需要跨域去拿,然而就在跨域的时候 vue-router 出了问题。

分析问题

我们的api站点在 api.com

而静态资源在 static.com,页面的base标签也指向static

<base href="http://static.com" rel="external nofollow" />

然而,在访问 test模板时却跳到了http://api.com/http:/static.com/test

经过一些简单的断点调试,锁定了以下代码

[source]: https://github.com/vuejs/vue-router/blob/dev/dist/vue-router.esm.js

 [vue-router.esm.js][source]

//1794行~1675行
function normalizeBase (base) {
 if (!base) {
  if (inBrowser) {
   // respect <base> tag
   var baseEl = document.querySelector('base');
   base = (baseEl && baseEl.getAttribute('href')) || '/';
  } else {
   base = '/';
  }
 }
 // make sure there's the starting slash
 if (base.charAt(0) !== '/') {
  base = '/' + base;
 }
 // remove trailing slash
 return base.replace(/\/$/, '')
}

这段代码的作用是设置路由的base路径,如果有兴趣一路跟踪的话会发现这个base参数是由实例化VueRouter时候传入的options.base

再看代码,他会判断如果base是空的,那么就会给一个默认值:

如果实在浏览器(非服务器环境)下执行,那么会调用document.querySelector('base')来尝试获取<base href='' />标签中href属性的值;

在我们实际的场景中,这里得到一个跨域的绝对地址,然后紧接着

if (base.charAt(0) !== '/') {
  base = '/' + base;
 }

当url第一个字符不是/的时候加上/,这里非常明显是一个BUG

我的是绝对地址http://static.com第一个字符当然不是/,所以才会由之前的http://api.com/http:/static.com/test这样的网址

修改

if(/^([a-z]+:)?\/\//i.test(base)){

}else if (base.charAt(0) !== '/') {
 base = '/' + base;
}

为了尽量少破坏源码,这里加了一个空的if,当url是由协议开始时,认为是绝对路径。

* 绝对路径还有一种形式是 //static.com

测试

经过第一次修改,再次访问页面依然有问题,访问的页面依然是http://api.com/http:/static.com/test

继续分析

再次跟踪源码后发现

[vue-router.esm.js][source]

//2006行~2016行
 HTML5History.prototype.push = function push (location, onComplete, onAbort) {
  var this$1 = this;

  var ref = this;
  var fromRoute = ref.current;
  this.transitionTo(location, function (route) {
   pushState(cleanPath(this$1.base + route.fullPath));
   handleScroll(this$1.router, route, fromRoute, false);
   onComplete && onComplete(route);
  }, onAbort);
 };
//561行~563行
function cleanPath (path) {
 return path.replace(/\/\//g, '/')
}

在发生pushState之前,他还会对url再次进行处理cleanPath

而这里的处理更简单,更粗暴,问题也更大。

他直接将2个斜杠//替换为1个斜杠/,话说如果连续3个斜杠怎么办?

所以在处理http://static.com/test地址的时候,其实会被处理成http:/static.com/test 又变成相对路径了...

继续修改

function cleanPath (path) {
  var ishttp = /^([a-z]+:)?\/\//i.exec(path);
  var http = Array.isArray(ishttp) ? ishttp[0] : '';
  return http + path.substr(http.length).replace(/\/{2,}/g, '/');
}

如果是协议开始,则排除协议内容之后,将2个或2个以上连续在一起的斜杠替换为1个斜杠。

** 完成提交pull

https://github.com/vuejs/vue-router/pull/1353/files

话说vue-router的url处理比起Url.js来说真的是太粗暴了...

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

Javascript 相关文章推荐
JavaScript 打地鼠游戏代码说明
Oct 12 Javascript
nullJavascript中创建对象的五种方法实例
May 07 Javascript
一个简单的JS时间控件示例代码(JS时分秒时间控件)
Nov 22 Javascript
jquery中的过滤操作详细解析
Dec 02 Javascript
判断JS对象是否拥有某种属性的两种方式
Dec 02 Javascript
JavaScript编程的10个实用小技巧
Apr 18 Javascript
Python脚本后台运行的几种方式
Mar 09 Javascript
JQuery选择器、过滤器大整理
May 26 Javascript
jQuery实现简单的DIV拖动效果
Feb 19 Javascript
强大的 Angular 表单验证功能详细介绍
May 23 Javascript
vue实现裁切图片同时实现放大、缩小、旋转功能
Mar 02 Javascript
解决iView Table组件宽度只变大不变小的问题
Nov 13 Javascript
JavaScript使用readAsDataUrl方法预览图片
May 10 #Javascript
Bootstrap table使用方法总结
May 10 #Javascript
将angular-ui的分页组件封装成指令的方法详解
May 10 #Javascript
vue-axios使用详解
May 10 #Javascript
详解axios在vue中的简单配置与使用
May 10 #Javascript
jQuery+PHP+Mysql实现抽奖程序
Apr 12 #jQuery
JavaScript实现form表单的多文件上传
Mar 27 #Javascript
You might like
php中mysql模块部分功能的简单封装
2011/09/30 PHP
PHP实现货币换算的方法
2014/11/29 PHP
php生成excel列名超过26列大于Z时的解决方法
2014/12/29 PHP
PHP页面转UTF-8中文编码乱码的解决办法
2015/10/20 PHP
php使用gearman进行任务分发操作实例详解
2020/02/26 PHP
Laravel中GraphQL接口请求频率实战记录
2020/09/01 PHP
jQuery 研究心得 取得属性的值
2007/11/30 Javascript
jquery图片延迟加载 前端开发技能必备系列
2012/06/18 Javascript
Jquery判断$(&quot;#id&quot;)获取的对象是否存在的方法
2013/09/25 Javascript
《JavaScript高级编程》学习笔记之object和array引用类型
2015/11/01 Javascript
js格式化时间的方法
2015/12/18 Javascript
基于Node.js实现nodemailer邮件发送
2016/01/26 Javascript
JavaScript 栈的详解及实例代码
2017/01/22 Javascript
EasyUI为Numberbox添加blur事件的方法
2017/03/05 Javascript
详解如何将angular-ui的图片轮播组件封装成一个指令
2017/05/09 Javascript
JS表单传值和URL编码转换
2018/03/03 Javascript
你应该了解的JavaScript Array.map()五种用途小结
2018/11/14 Javascript
taro开发微信小程序的实践
2019/05/21 Javascript
JS面向对象之单选框实现
2020/01/17 Javascript
浅谈vue中get请求解决传输数据是数组格式的问题
2020/08/03 Javascript
Python简单实现enum功能的方法
2016/04/25 Python
python使用正则表达式来获取文件名的前缀方法
2018/10/21 Python
使用python分析统计自己微信朋友的信息
2019/07/19 Python
Python3基于plotly模块保存图片表格
2020/08/03 Python
Python如何爬取51cto数据并存入MySQL
2020/08/25 Python
python实现图像随机裁剪的示例代码
2020/12/10 Python
英国音乐设备和乐器商店:Gear4music
2017/10/16 全球购物
美国气象仪器、花园装饰和墙壁艺术商店:Wind & Weather
2019/05/29 全球购物
高三学习决心书
2014/03/11 职场文书
聚美优品陈欧广告词
2014/03/14 职场文书
农村产权制度改革实施方案
2014/03/21 职场文书
六一儿童节演讲稿
2014/05/23 职场文书
运动会班级前导词
2015/07/20 职场文书
Java Shutdown Hook场景使用及源码分析
2021/06/15 Java/Android
Python可视化学习之seaborn绘制矩阵图详解
2022/02/24 Python
win10系统xps文件怎么打开?win10打开xps文件的两种操作方法
2022/07/23 数码科技