关于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 相关文章推荐
jQuery 添加/移除CSS类实现代码
Feb 11 Javascript
浅谈Javascript面向对象编程
Nov 15 Javascript
IE下JS读取xml文件示例代码
Aug 05 Javascript
js简单实现让文本框内容逐个字的显示出来
Oct 22 Javascript
Uploadify上传文件方法
Mar 16 Javascript
javascript事件模型介绍
May 31 Javascript
用angular实现多选按钮的全选与反选实例代码
May 23 Javascript
JS表单传值和URL编码转换
Mar 03 Javascript
vue路由组件按需加载的几种方法小结
Jul 12 Javascript
JavaScript中七种流行的开源机器学习框架
Oct 11 Javascript
Vue利用History记录上一页面的数据方法实例
Nov 02 Javascript
深入理解redux之compose的具体应用
Jan 12 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教程 插件机制在PHP中实现方案
2012/11/02 PHP
PHP实现文件下载断点续传详解
2014/10/15 PHP
PHP使用PDO抽象层获取查询结果的方法示例
2018/05/10 PHP
php使用redis的有序集合zset实现延迟队列应用示例
2020/02/20 PHP
jquery实现可拖拽弹出层特效
2015/01/04 Javascript
javascript实现避免页面按钮重复提交
2015/01/08 Javascript
jQuery使用CSS()方法给指定元素同时设置多个样式
2015/03/26 Javascript
浅析在javascript中创建对象的各种模式
2016/05/06 Javascript
Jquery $when done then的用法详解
2016/05/20 Javascript
jQuery实现页面点击后退弹出提示框的方法
2016/08/24 Javascript
vue.js源代码core scedule.js学习笔记
2017/07/03 Javascript
bootstrap table实现横向合并与纵向合并
2019/07/18 Javascript
Vuex的实战使用详解
2019/10/31 Javascript
一看就会的vuex实现登录验证(附案例)
2020/01/09 Javascript
JavaScript禁止右击保存图片,禁止拖拽图片的实现代码
2020/04/28 Javascript
vue 组件之间事件触发($emit)与event Bus($on)的用法说明
2020/07/28 Javascript
JavaScript通如何过RGraph实现动态仪表盘
2020/10/15 Javascript
python2 与python3的print区别小结
2018/01/16 Python
Python的多维空数组赋值方法
2018/04/13 Python
Python编程flask使用页面模版的方法
2018/12/28 Python
Python绘图实现显示中文
2019/12/04 Python
利用python中集合的唯一性实现去重
2020/02/11 Python
Python requests模块cookie实例解析
2020/04/14 Python
pytorch查看通道数 维数 尺寸大小方式
2020/05/26 Python
如何真正的了解python装饰器
2020/08/14 Python
python 将html转换为pdf的几种方法
2020/12/29 Python
Square Off美国/加拿大:世界上最聪明的国际象棋棋盘
2018/12/06 全球购物
英国和世界各地预订便宜的酒店:LateRooms.com
2019/05/05 全球购物
优秀大学生推荐信范文
2013/11/28 职场文书
高三语文教学反思
2014/01/15 职场文书
软件部经理岗位职责范本
2014/02/25 职场文书
公司年会搞笑主持词
2014/03/24 职场文书
工商局副局长个人对照检查材料
2014/09/25 职场文书
大学生心理健康活动总结
2015/05/08 职场文书
幼儿园托班教育随笔
2015/08/14 职场文书
3050和2060哪个好 性能差多少 差距有多大 谁更有性价比
2022/06/17 数码科技