Vue Router history模式的配置方法及其原理


Posted in Javascript onMay 30, 2019

vue-router分为 hashhistory模式,前者为其默认模式,url的表现形式为 http://yoursite.com#home,比较难看。后者的url表现形式为 http://yoursite.com/home,比较美观。

但如果要使用 history模式,我们需要在后端进行额外配置。本文将讨论如何配置以及为什么要这样配置。

history模式的配置方法

我们来看看官方文档是教我们怎么配置的:HTML5 History 模式。

首先要将 mode设置为 history

const router = new VueRouter({
 mode: 'history',
 routes: [...]
})

然后设置后端(这里采用的nginx):

location / {
 try_files $uri $uri/ /index.html;
}

然后就......没了!显然官方的教程讲的比较简略,并且我们参照这个教程实际上还是会遇到一些问题。

history模式的配置实践及原理

强烈建议:阅读这部分之前,先看一下nginx的这部分文档和 这部分文档。

既然官方文档教我们这样做了,我们就按照它说的来实践一下。

只配置前端的情况

首先,我们将 mode设置为 history,但不配置后端。然后,假如我们的路由是长这个样子的:

const routes = [
  {path: '/home', component: Home},
  {path: '/', redirect: '/home'}
];

我们用nginx部署项目,然后在地址栏输入 http://localhost:8080(这里配置的端口是8080),你会发现地址栏之后会变为 http://localhost:8080/home,并且 看起来一切正常, 似乎路由也可以正常切换而不会发生其他问题(实际上会发生问题,后面会进行讨论)。看起来好像不需要按官网告诉我们的那样配置后端也能实现 history模式,但如果你直接在地址栏输入 http://localhost:8080/home,你会发现你获得了一个404页面。

那么 http://localhost:8080为什么可以(部分)正常显示呢?道理其实很简单,你访问 http://localhost:8080时,静态服务器(这里是nginx)会默认去目标目录(这里为 locationroot所指定的目录)下寻找 index.html(这是nginx在端口后没有额外路径时的默认行为),目标目录下有这个文件吗?有!然后静态服务器返回给你这个文件,配合 vue-router进行转发,自然可以(部分)正常显示。

但如果直接访问 http://localhost:8080/home,静态服务器会去目标目录下寻找 home文件,目标目录下有这个文件吗?没有!所以自然就404了。

配置后端

为了达到直接访问 http://localhost:8080/home也可以成功的目的,我们需要对后端(这里即nginx)进行一些配置。

首先想想,要怎样才能达到这个目的呢?

在传统的 hash模式中( http://localhost:8080#home),即使不需要配置,静态服务器始终会去寻找 index.html并返回给我们,然后 vue-router会获取 #后面的字符作为参数,对前端页面进行变换。

类比一下,在 history模式中,我们所想要的情况就是:输入 http://localhost:8080/home,但最终返回的也是 index.html,然后 vue-router会获取 home作为参数,对前端页面进行变换。那么在nginx中,谁能做到这件事呢?答案就是 try_files

首先看一下try_files的语法: try_files file ... uri;

然后看一下官方文档对它的介绍:

Checks the existence of files in the specified order and uses the first found file for request processing; the processing is performed in the current context. The path to a file is constructed from the file parameter according to the root and alias directives. It is possible to check directory's existence by specifying a slash at the end of a name, e.g. “$uri/”. If none of the files were found, an internal redirect to the uri specified in the last parameter is made.

大意就是它会按照 try_files后面的参数依次去匹配 root中对应的文件或文件夹。如果匹配到的是一个文件,那么将返回这个文件;如果匹配到的是一个文件夹,那么将返回这个文件夹中 index指令指定的文件。最后一个 uri参数将作为前面没有匹配到的fallback。(注意 try_files指令至少需要两个参数)

拿我自己的网站举个例子:

location / { 
    root      /data/www/rf-blog-web; 
    index      index.html; 
    try_files    $uri $uri/ /index.html; 
}

$uri是nginx中的变量,比如我访问的网址是 http://localhost:8080/home,那么它就代表的 /home

rf-blog-web这个目录中,没有子目录,只有一个 index.html和一些压缩后的名称是hash值的.js文件。当我们请求 http://localhost:8080/home这个地址时,首先查找有无 home这个文件,没有;再查找有无 home目录,也没有。所以最终会定位到第三个参数从而返回 index.html,按照这个规则,所有路由里的url路径最后都会定位到 index.htmlvue-router再获取参数进行前端页面的变换,至此,我们已经可以通过 http://localhost:8080/home这个地址进行成功地访问了。

$uri这个参数的作用其实是匹配那些.js文件用的,而 $uri/在这个例子中并没有多大用,实际上是可以去掉的。

history模式下可能会遇到的问题及解决方案

在将我的项目(在路由中用了懒加载)改为 history模式的过程中,有时候发现会出现chunk加载出错的情况,打开chrome的network发现那个chunk加载404了,是因为请求的url中多了一层路径。我在这里发现了解决方案。

LinusBorg说,因为在 history模式中切换路由时,我们是真正改变了页面的url路径,所以webpack的runtime会认为它位于 example.com/some/path。如果 publicPath是设置的相对路径,那么webpack加载chunk时可能会变成 example.com/some/path/static/js/3.js这样的路径,然而chunk的真正路径是 example.com/static/js/3.js,所以我们需要将 publicPath设置为绝对路径( publicPath: '/')来解决这个问题。

总结

以上所述是小编给大家介绍的Vue Router history模式的配置方法及其原理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jqgrid 简单学习笔记
May 03 Javascript
通过jquery的$.getJSON做一个跨域ajax请求试验
May 03 Javascript
基于jQuery的图片剪切插件
Aug 03 Javascript
JavaScript面向对象的实现方法小结
Apr 14 Javascript
js模仿php中strtotime()与date()函数实现方法
Aug 11 Javascript
js实现密码强度检测【附示例】
Mar 30 Javascript
jQuery实现模拟搜索引擎的智能提示功能简单示例
Jan 27 jQuery
微信小程序实现的一键连接wifi功能示例
Apr 24 Javascript
Vue在chrome44偶现点击子元素事件无法冒泡的解决方法
Dec 15 Javascript
Vue-resource安装过程及使用方法解析
Jul 21 Javascript
vant中的toast轻提示实现代码
Nov 04 Javascript
Vue 修改网站图标的方法
Dec 31 Vue.js
vue-cli3+ts+webpack实现多入口多出口功能
May 30 #Javascript
详解Vue项目引入CreateJS的方法(亲测可用)
May 30 #Javascript
了解JavaScript函数中的默认参数
May 30 #Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
May 30 #Javascript
轻松学习JavaScript函数中的 Rest 参数
May 30 #Javascript
细说Vue组件的服务器端渲染的过程
May 30 #Javascript
了解JavaScript中let语句
May 30 #Javascript
You might like
一道求$b相对于$a的相对路径的php代码
2010/08/08 PHP
解决PHP在DOS命令行下却无法链接MySQL的技术笔记
2010/12/29 PHP
PHP面向对象编程之深入理解方法重载与方法覆盖(多态)
2015/12/24 PHP
[原创]PHP实现SQL语句格式化功能的方法
2017/07/28 PHP
js中top、clientTop、scrollTop、offsetTop的区别 文字详细说明版
2011/01/08 Javascript
Javascript this 的一些学习总结
2012/08/02 Javascript
原生js事件的添加和删除的封装
2014/07/01 Javascript
浅谈Javascript变量作用域问题
2014/12/16 Javascript
JavaScript中字符串(string)转json的2种方法
2015/06/25 Javascript
在页面中输出当前客户端时间javascript实例代码
2016/03/02 Javascript
实例解析jQuery工具函数
2016/12/01 Javascript
js css3实现图片拖拽效果
2017/03/04 Javascript
angular-ngSanitize模块-$sanitize服务详解
2017/06/13 Javascript
bootstrap可编辑下拉框jquery.editable-select
2017/10/12 jQuery
基于Vue2的独立构建与运行时构建的差别(详解)
2017/12/06 Javascript
详解JavaScript的BUG和错误
2018/05/07 Javascript
微信小程序实践之动态控制组件的显示/隐藏功能
2018/07/18 Javascript
vue项目中使用Svg的方法
2018/10/24 Javascript
UEditor 自定义图片视频尺寸校验功能的实现代码
2020/10/20 Javascript
python学生管理系统代码实现
2020/04/05 Python
Python实现抓取HTML网页并以PDF文件形式保存的方法
2018/05/08 Python
numpy判断数值类型、过滤出数值型数据的方法
2018/06/09 Python
Tensorflow 多线程与多进程数据加载实例
2020/02/05 Python
Python如何读写CSV文件
2020/08/13 Python
CSS3实现淘宝留白的方法
2020/06/05 HTML / CSS
网页中的电话号码如何实现一键直呼效果_附示例
2016/03/15 HTML / CSS
html5-Canvas可以在web中绘制各种图形
2012/12/26 HTML / CSS
MVMT手表官方网站:时尚又实惠的高品质手表
2016/12/04 全球购物
SportsDirect.com新加坡:英国第一体育零售商
2019/03/30 全球购物
LINUX下线程,GDI类的解释
2012/04/17 面试题
汽车专业毕业生推荐信
2013/11/12 职场文书
父亲生日宴会答谢词
2014/01/10 职场文书
Css预编语言及区别详解
2021/04/25 HTML / CSS
微信小程序基础教程之echart的使用
2021/06/01 Javascript
根德5570型九灯四波段立体声收音机是电子管收音机的楷模 ? 再论5570
2022/04/05 无线电
Redis高并发缓存架构性能优化
2022/05/15 Redis