关于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的Cookies
Jan 16 Javascript
支持ie与FireFox的剪切板操作代码
Sep 28 Javascript
Jquery 改变radio/checkbox选中状态,获取选中的值(示例代码)
Dec 12 Javascript
js限制文本框只能输入数字方法小结
Jun 16 Javascript
分享15个大家都熟知的jquery小技巧
Dec 02 Javascript
jQuery实现的鼠标经过时变宽的效果(附demo源码)
Apr 28 Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
Sep 08 Javascript
jquery实现下拉框多选方法介绍
Jan 03 Javascript
JavaScript解析任意形式的json树型结构展示
Jul 23 Javascript
使用cookie绕过验证码登录的实现代码
Oct 12 Javascript
JS手机端touch事件计算滑动距离的方法示例
Oct 26 Javascript
详解js根据百度地图提供经纬度计算两点距离
May 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 操作符与控制结构
2012/03/07 PHP
thinkPHP删除前弹出确认框的简单实现方法
2016/05/16 PHP
Yii2 assets清除缓存的方法
2016/05/16 PHP
PHP magento后台无法登录问题解决方法
2016/11/24 PHP
thinkphp3.2实现在线留言提交验证码功能
2017/07/19 PHP
php高清晰度无损图片压缩功能的实现代码
2018/12/09 PHP
PHP hebrev()函数用法讲解
2019/02/21 PHP
js定时调用方法成功后并停止调用示例
2014/04/08 Javascript
基于豆瓣API+Angular开发的web App
2015/01/02 Javascript
js实现感应鼠标图片透明度变化的方法
2015/02/20 Javascript
js随机生成字母数字组合的字符串 随机动画数字
2015/09/02 Javascript
JS实现点击登录弹出窗口同时背景色渐变动画效果
2016/03/25 Javascript
jQuery自定义数值抽奖活动代码
2016/06/11 Javascript
JavaScript函数节流概念与用法实例详解
2016/06/20 Javascript
JS 面向对象之继承---多种组合继承详解
2016/07/10 Javascript
jQuery中 $ 符号的冲突问题及解决方案
2016/11/04 Javascript
网站发布后Bootstrap框架引用woff字体无法正常显示的解决方法
2016/11/24 Javascript
微信小程序 石头剪刀布实例代码
2017/01/04 Javascript
nodejs基础知识
2017/02/03 NodeJs
JS原型与原型链的深入理解
2017/02/15 Javascript
C#程序员入门学习微信小程序的笔记
2019/03/05 Javascript
AngularJS实现的鼠标拖动画矩形框示例【可兼容IE8】
2019/05/17 Javascript
vue动态子组件的两种实现方式
2019/09/01 Javascript
JavaScript进制转换实现方法解析
2020/01/18 Javascript
vue实现两个组件之间数据共享和修改操作
2020/11/12 Javascript
vue祖孙组件之间的数据传递案例
2020/12/07 Vue.js
[02:06]2018完美世界全国高校联赛秋季赛开始报名(附彩蛋)
2018/09/03 DOTA
Python框架Flask的基本数据库操作方法分析
2018/07/13 Python
Python中的函数式编程:不可变的数据结构
2018/10/08 Python
Python 单例设计模式用法实例分析
2019/09/23 Python
浅谈TensorFlow之稀疏张量表示
2020/06/30 Python
selenium设置浏览器为headless无头模式(Chrome和Firefox)
2021/01/08 Python
CSS3之transition实现下划线的示例代码
2018/05/30 HTML / CSS
HTML5的video标签的浏览器兼容性增强方案分享
2016/05/19 HTML / CSS
大学生职业生涯规划书参考模板
2014/03/05 职场文书
难以忽视的真相观后感
2015/06/05 职场文书