$$tip

本章主要介绍为什么会有两种模式和它们的机制,有关两种模式的配置可以参考官方文档,不同的历史记录模式

$$

以下是指向同一个页面的两种模式的链接。

https://example.com/#/user // hash
https://example.com/user // HTML5

为什么存在两种模式?

通常来说,我们平时的文件跟域名路径都是一一对应的,比如以下的文件目录,对应到域名路径上就应该如下。

https://example.com // 显示 index.html 文件
https://example.com/index.html // 显示 index.html 文件
https://example.com/user.html // 显示 user.html 文件
https://example.com/about.html // 显示 about.html 文件

image

问题来了, Vue 打包生成的页面只有一个 index.html 文件。

如下图, dist 文件夹是运行 npm run build 打包后生成的文件目录,可见只有一个 index.html 文件。这也 Vue 被称为单页面应用(single page web application,SPA)。

image

那么是否意味着 Vue 都只能有一个页面了呢,不是的。 通过 hash 模式的链接,会把所有的页面请求都指向 index.html 文件,因为 # 本质上只是一个锚定位。

$$jsdemo$$
$$edit$$
const url = new URL("https://example.com/#/user")

alert(url.pathname) // 打印(/),文件指向 index.html
alert(url.hash) // 打印(#/user)

hash 模式

我们可以简单用原生的前端代码通过 hash 模式实现多个页面的效果。

<!-- index.html -->
<div id="app"></div>
<script>
    // hash 模式
    switch (document.location.hash) {
        case "#/":
            app.outerHTML = "<h1>首页</h1>"
            break
        case "#/user":
            app.outerHTML = "<h1>用户页面</h1>"
            break
        case "#/about":
            app.outerHTML = "<h1>关于页面</h1>"
            break
        default:
            app.outerHTML = "<h1>404,未找到页面。</h1>"
            break
    }
</script>

代码虽简陋,但也表明 Vue Router 中 hash 模式的机制。

HTML5 模式

由于 hash 模式终究只是锚定位,一是链接不雅观,与传统链接有区别,二是不利于 SEO(搜索引擎优化),因为搜索引擎爬虫会把所有锚定位的链接当成一个页面。

因此便有了 HTML5 模式。

<!-- index.html -->
<div id="app"></div>
<script>
    // HTML5 模式
    switch (document.location.pathname) {
        case "/":
            app.outerHTML = "<h1>首页</h1>"
            break
        case "/user":
            app.outerHTML = "<h1>用户页面</h1>"
            break
        case "/about":
            app.outerHTML = "<h1>关于页面</h1>"
            break
        default:
            app.outerHTML = "<h1>404,未找到页面。</h1>"
            break
    }
</script>

问题又来了,通过路径的形式那么服务器会返回对应的文件,比如以上会分别返回 userabout 文件等等。这些文件在服务器中并不存在,那么只会返回 404 错误(找不到对应文件)。

因此,使用 HTML5 模式必须配置服务器的相关代理工具,使其任何路径都指向 index.html 文件,然后再在 index.html 根据链接的路径名返回对应的页面内容。

查看 Vue Router 官方文档中对于 HTML5 模式的服务器配置示例