Vue 预设是使用 hash 模式,但可选择使用 history 模式。hash 模式时的 URL 会带 #
符号,例如 https://example.com/#/about
跳转时不会发出 HTTP 请求,只会按 #
後的内容来显示相应的元件。
history 模式不会带 #
,例如 https://example.com/about
。跳转页面时会发 HTTP 请求。背後原理是使用 Web History API 和 建构 Router 来避免重刷页面。但注意,history 模式需配合後端设定,把找不到的路由全都指向 index.html
,才不会出现 404 的问题。
以下会再作详细解说。
#
後内容的变化。#
前的路由,并把首页回传给你,之後所有跳转页面都不会发出 HTTP 请求。所以使用者其实是一直停留在 index.html,并在此档案上切换显示不同元件来模拟跳转页面。#
符号。#
後的内容,因为会把 #
当作是锚点。<a href="#about"> About Us </a>
<h2 id="about">
...
</h2>
pushState()
和replaceState()
方法,以及浏览器的 popstate 事件来实现。当 URL 有变,就会 window.location.pathname
来取出路由内容,再在建构 router 物件时,利用 route 的物件把该 pathname 值对应到指定的元件。过程不会重刷页面。pushState()
更换 URL、存入浏览记录等。https://www.example.com/product/111
,会出现 404 页面,因为服务器会去查看有没有 product/111
这个路由来处理这个 HTTP 请求,最後因为没找到所以就回 404页面。以 Node.js 的 Express.js 框架为例。个人对後端的认识不多,只能以自己过往写 Express.js 来设定服务器作例子,让我们更清楚明白以上提到服务器找不到路由的意思。
先看看 Express.js 最简单的起手式:
app.js
var express = require('express');
var app = express();
// URL:http://localhost:3000
app.get('/', function(req,res){
res.send('首页');
})
// URL:http://localhost:3000/user
app.get('/user', function(req,res){
res.send('个人页面');
})
// 如果没有对应到以上任何一个 URL,最後就会执行以下程序码
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
如上做法,跟前端设定 404 页面的原理是一样。程序码由上到下执行,当 HTTP 请求进来时,如果在这里找不到此请求的 URL,最後就会执行回传 404 错误的程序码。
因此,後端服务器需要设定,如果没找到对应的路由,就一律回传 index.html。注意,虽然有发出 http 请求,但是以上提过,Vue 是使用 HTML5 history API 以及建构 route 物件的方法,避免了重刷页面,并实现切换页面的效果。因此跳转页面时不会重刷页面。
以上讲了很多原理,但实际上回传 404 的情况是怎样?以下将示范一次,使用 history 模式时,到底如何会发生 404 问题。
首先使用 Vue CLI 建立一个 Vue 专案,并选择包含 router 功能,router 使用 history mode。
之後打开档案,输入 npm run build
打包一次专案,产生 dist 资料夹。把 dist 资料夹拖到 VScode 里打开,并打开 index.html,再使用 live server 浏览这个档案,你会发现刚载入网页後,URL 是 http://127.0.0.1:5500/index.html
,但内容是空的:
那是因为现在是直接用 live serve 浏览 index.html 档案。如果你直接访问 http://127.0.0.1:5500/
就会成功显示:
然後,尝试按下 About 按钮,发现 URL 变成http://127.0.0.1:5500/about
,有成功渲染 about 元件:
再按 Home 按钮,也有成功渲染 Home 元件,URL 变成 http://127.0.0.1:5500/
:
http://127.0.0.1:5500/about
但当你试着直接访问 http://127.0.0.1:5500/about
此 URL,会出现 404 页面:
或者,你可以试试在第二步,成功打开 About 页面时,再重刷页面,也同样是会出现 404 页面。
现在我们逐一理解原因。
第一步,服务器收到 /
的请求时,会正常指向 index.html,并让 Vue 使用 Web History API 和建构 Router 物件来把 pathname 与指定元件对应起来。
第三步,当你直接访问 http://127.0.0.1:5500/about
,就会向後端服务器发出 /about
这个 GET 请求,但是服务器没有设定处理 /about
这路由,因此回传 404。
那为什麽在第 2 步,可以成功打开 About 页?个人理解是,因为我们不是直接访问 About页,而是透过打开了首页,再按 Nav bar 的 About 来进入 About 页。因此,这里的流程是:你先载入了 index.html,之後就开始使用 Web History API,跑以上提过的流程,把 pathname 对应到指定元件,成功把 About 元件显示出来。
从以上情况得知,要避免以上 404 的情况,在服务器就需要把所有找不到的 URL 一律指向 index.html
。例如,当你直接访问 http://127.0.0.1:5500/about
时,就会指向 index.html
,然後 Vue 就会跑 Web history API,由 index.html
里的 Vue router 去把 pathname 对应到指定元件。
#
,跳转时不会发出 HTTP 请求。限制是不利 SEO,以及会与锚点功能有冲突等。#
,跳转时会发出 HTTP 请求。限制是浏览器兼容性较差,以及後端需要自行设定,避免 404 问题。原来这就是hash模式和history模式的区别(vue-router mode)
Using Vue Router History Mode
<<: Day 19: Behavioral patterns - Command
>>: 30天学会 Python: Day 18-try try 看
NextAuth + JWT authentication 虽然 Next.js 的定位是一个全端框...
今天会针对一个services进行单元测试,并详述过程 config 首先先介绍基本的测试所安装的g...
Social engineering可以采取多种形式,包括网络钓鱼电子邮件,假冒网站 及冒名顶替。 ...
在第一篇介绍时提到Html就像礼物的实体,而我们现在要认识的CSS样式表就像是礼物的外包装,要如何包...