关于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 相关文章推荐
web基于浏览器的本地存储方法应用
Nov 27 Javascript
JS 按钮点击触发(兼容IE、火狐)
Aug 07 Javascript
JavaScript—window对象使用示例
Dec 09 Javascript
JavaScript中诡异的delete操作符
Mar 12 Javascript
Javascript使用post方法提交数据实例
Aug 03 Javascript
JavaScript中String对象的方法介绍
Jan 04 Javascript
vue实现城市列表选择功能
Jul 16 Javascript
vue 界面刷新数据被清除 localStorage的使用详解
Sep 16 Javascript
微信小程序实现的绘制table表格功能示例
Apr 26 Javascript
Vue实现滑动拼图验证码功能
Sep 15 Javascript
JavaScript交换两个变量方法实例
Nov 25 Javascript
Nest.js 授权验证的方法示例
Feb 22 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
CodeIgniter配置之routes.php用法实例分析
2016/01/19 PHP
php服务器的系统详解
2019/10/12 PHP
Laravel 框架返回状态拦截代码
2019/10/18 PHP
php 使用html5 XHR2实现上传文件与进度显示功能示例
2020/03/03 PHP
详解使用php-cs-fixer格式化代码
2020/09/16 PHP
jquery插件制作 自增长输入框实现代码
2012/08/17 jQuery
js如何实现设计模式中的模板方法
2013/07/23 Javascript
JS实现超精简响应鼠标显示二级菜单代码
2015/09/12 Javascript
浅析JS运动
2015/12/28 Javascript
JS onkeypress兼容性写法详解
2016/04/27 Javascript
js ajaxfileupload.js上传报错的解决方法
2016/05/05 Javascript
JavaScript作用域示例详解
2016/07/07 Javascript
Angular ng-class详解及实例代码
2016/09/19 Javascript
js实现目录链接,内容跟着目录滚动显示的简单实例
2016/10/15 Javascript
JAVA Web实时消息后台服务器推送技术---GoEasy
2016/11/04 Javascript
jquery无法为动态生成的元素添加点击事件的解决方法(推荐)
2016/12/26 Javascript
Node+Express+MongoDB实现登录注册功能实例
2017/04/23 Javascript
dropload.js插件下拉刷新和上拉加载使用详解
2017/10/20 Javascript
vue中前进刷新、后退缓存用户浏览数据和浏览位置的实例讲解
2018/09/21 Javascript
nodejs检测因特网是否断开的解决方案
2019/04/17 NodeJs
简单实现节流函数和防抖函数过程解析
2019/10/08 Javascript
Node.js API详解之 V8模块用法实例分析
2020/06/05 Javascript
微信小程序实现签到弹窗动画
2020/09/21 Javascript
python通过ElementTree操作XML获取结点读取属性美化XML
2013/12/02 Python
python多线程编程方式分析示例详解
2013/12/06 Python
python解析html开发库pyquery使用方法
2014/02/07 Python
python如何保证输入键入数字的方法
2019/08/23 Python
Python定时器线程池原理详解
2020/02/26 Python
Python使用pickle进行序列化和反序列化的示例代码
2020/09/22 Python
标签和贴纸印刷:Lightning Labels
2018/03/22 全球购物
Farfetch台湾官网:奢侈品牌时尚购物平台
2019/06/17 全球购物
秦兵马俑教学反思
2014/02/07 职场文书
反腐倡廉标语
2014/06/24 职场文书
高一地理教学工作总结
2015/08/12 职场文书
优秀党员主要事迹材料
2015/11/04 职场文书
JavaScript文档对象模型DOM
2021/11/20 Javascript