关于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 相关文章推荐
ext checkboxgroup 回填数据解决
Aug 21 Javascript
javascript写的一个链表实现代码
Oct 25 Javascript
基于jquery的无缝循环新闻列表插件
Mar 07 Javascript
jQuery实现分章节锚点“回到顶部”动画特效代码
Oct 23 Javascript
Vue.js学习笔记之 helloworld
Aug 14 Javascript
Angular表单验证实例详解
Oct 20 Javascript
JS定时器实现数值从0到10来回变化
Dec 09 Javascript
详解关于react-redux中的connect用法介绍及原理解析
Sep 11 Javascript
Next.js项目实战踩坑指南(笔记)
Nov 29 Javascript
JavaScript事件对象深入详解
Dec 30 Javascript
Layui实现主窗口和Iframe层参数传递
Nov 14 Javascript
jQuery实现小火箭返回顶部特效
Feb 03 jQuery
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
《DOTA3》开发工作已经开始 《DOTA3》将代替《DOTA2》
2021/03/06 DOTA
phplist及phpmailer(组合使用)通过gmail发送邮件的配置方法
2016/03/30 PHP
比较全面的event对像在IE与FF中的区别 推荐
2009/09/21 Javascript
jquery的index方法实现tab效果
2011/02/16 Javascript
全面理解面向对象的 JavaScript(来自ibm)
2013/11/10 Javascript
jQuery子窗体取得父窗体元素的方法
2015/05/11 Javascript
使用javascript插入样式
2016/03/14 Javascript
微信小程序 数据绑定详解及实例
2016/10/25 Javascript
Node.js通过身份证号验证年龄、出生日期与性别方法示例
2017/03/09 Javascript
微信小程序 标签传入数据
2017/05/08 Javascript
基于JavaScript实现无缝滚动效果
2017/07/21 Javascript
vuejs使用$emit和$on进行组件之间的传值的示例
2017/10/04 Javascript
在vue项目中引入highcharts图表的方法(详解)
2018/03/05 Javascript
Vue项目报错:Uncaught SyntaxError: Unexpected token
2018/11/10 Javascript
layer弹出层扩展主题的方法
2019/09/11 Javascript
vue项目初始化到登录login页面的示例
2019/10/31 Javascript
Vue+Bootstrap收藏(点赞)功能逻辑与具体实现
2020/10/22 Javascript
写一个Vue loading 插件
2020/11/09 Javascript
[01:02:04]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
Python时间戳使用和相互转换详解
2017/12/11 Python
Python实现的HMacMD5加密算法示例
2018/04/03 Python
pandas 数据实现行间计算的方法
2018/06/08 Python
基于python实现FTP文件上传与下载操作(ftp&amp;sftp协议)
2020/04/01 Python
PHP基于phpqrcode类库生成二维码过程解析
2020/05/28 Python
html5的pushstate以及监听浏览器返回事件的实现
2020/08/11 HTML / CSS
巴西体育用品商店:Lojão dos Esportes
2018/07/21 全球购物
顶撞老师检讨书
2014/02/07 职场文书
优秀团干部个人事迹
2014/05/29 职场文书
社区清明节活动总结
2014/07/04 职场文书
法人单位适用的授权委托书
2014/09/19 职场文书
感谢信模板大全
2015/01/23 职场文书
吧主申请感言怎么写
2015/08/03 职场文书
《女娲补天》读后感5篇
2019/12/31 职场文书
超外差式晶体管收音机的组装与统调
2021/04/22 无线电
15个值得收藏的JavaScript函数
2021/09/15 Javascript
Python批量解压&压缩文件夹的示例代码
2022/04/04 Python