Code前端首页关于Code前端联系我们

刚接触Vue Router的同学,大概率会纠结,history模式到底是啥?项目里咋用?部署到服务器咋老报404?这篇文章把这些问题拆碎了讲,看完你就门儿清~

terry 4小时前 阅读数 8 #Vue

Vue Router history模式是啥?

先回忆下Vue Router的路由模式,默认是hash模式,URL里带个,比如http://xxx.com/#/about,而history模式是另一种路由模式,它的URL长这样:http://xxx.com/about,没有,更像普通网站的URL,好看又专业。

它能实现这效果,靠的是HTML5 History API里的pushStatereplaceState方法,这俩方法允许咱在不刷新页面的情况下,修改浏览器的历史记录,同时改变URL,Vue Router就是基于这俩API,让前端路由切换时,URL跟着变,但页面不用重新加载,体验更流畅。

举个例子:用户点导航栏的“关于我们”,history模式下,URL从首页变成/about,同时Vue Router加载对应的About组件,整个过程页面不刷新,用户感觉跟原生APP切换页面一样丝滑。

咋在项目里开启history模式?

配置特别简单,就改一行代码!在创建Vue Router实例的时候,把mode属性设为'history'就行,看例子:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'
Vue.use(VueRouter)
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]
// 关键配置:mode: 'history'
const router = new VueRouter({
  mode: 'history', 
  routes
})
export default router

配置完后,启动项目看看URL,原来的没了,路由切换时URL也会跟着变,比如从根路径跳到About页面,URL变成http://localhost:8080/about,是不是清爽多了?

不过要注意:开发环境(比如Vue CLI启动的dev server)里,这种配置不会有问题,因为开发服务器已经帮咱处理了路由跳转,但部署到生产环境时,麻烦才刚开始……

部署history模式项目,为啥总遇到404?咋解决?

很多同学部署后,直接访问首页()没问题,但刷新子路由(比如/about)就报404,这不是你代码写错了,而是服务器和单页应用(SPA)的工作逻辑导致的。

咱得先明白:SPA的路由是前端路由,意思是所有路由逻辑都在浏览器里处理,服务器上真正存在的文件只有index.html,其他像/about这种路径,服务器里根本没有对应的文件,所以当你直接在浏览器输入/about,服务器会找这个路径的文件,找不到就返回404。

解决思路很简单:让服务器把所有路由请求,都转发到index.html,让前端Vue Router来处理路由,下面分不同服务器讲配置方法:

Nginx服务器配置

打开Nginx的配置文件(一般在/etc/nginx/conf.d//usr/local/nginx/conf/),在server块里加这段:

location / {
  root /usr/share/nginx/html; # 你的项目dist目录路径
  index index.html index.htm;
  try_files $uri $uri/ /index.html; # 关键配置:尝试访问文件→目录→转发到index.html
}

try_files的作用是:先找请求的文件(比如/about对应的文件,不存在),再找对应的目录(也不存在),最后转发到/index.html,这样前端Vue Router就能接管路由,不会404了。

Apache服务器配置

需要开启mod_rewrite模块,然后在项目根目录(dist目录)新建.htaccess文件,写入:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

解释下:先开Rewrite引擎,然后判断请求的文件(!-f)和目录(!-d)是否不存在,如果不存在,就转发到index.html

Node.js(Express框架)配置

如果用Node.js做后端,比如Express,需要在代码里处理所有路由,转发到index.html,示例代码:

const express = require('express')
const path = require('path')
const app = express()
// 静态文件托管(dist目录)
app.use(express.static(path.join(__dirname, 'dist')))
// 所有请求都返回index.html
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
const port = process.env.PORT || 3000
app.listen(port, () => {
  console.log(`Server running on port ${port}`)
})

这样不管用户访问哪个路径,都会返回index.html,前端路由就能正常工作啦~

history模式和hash模式有啥区别?咋选?

很多同学纠结选哪个模式,咱从URL外观、原理、后端配置、兼容性这几点对比下:

对比项 history模式 hash模式
URL外观 无#,如http://xxx.com/about 有#,如http://xxx.com/#/about
底层原理 HTML5 History API(pushState/replaceState 监听hashchange事件(URL中#后的变化)
后端配置 需要配置(否则刷新404) 不需要(因为#后的内容不会传给服务器)
兼容性 IE10+(HTML5新特性) IE8+(hashchange事件兼容性好)
适用场景 追求URL美观、不需要兼容旧浏览器 需要兼容IE8/9,或快速部署不想配后端

简单说:如果项目面向现代浏览器,想要更专业的URL,选history模式(记得配后端);如果要兼容老浏览器,或者快速上线不想折腾服务器,选hash模式更省心。

用history模式开发,这些坑要避开!

除了部署,开发过程中还有些细节得注意,不然容易踩坑:

开发环境 vs 生产环境

Vue CLI的开发服务器(npm run serve)已经处理了路由转发,所以开发时刷新子路由不会404,但生产环境必须配服务器,否则一刷新就崩,所以开发时要记得,部署前先测服务器配置。

路由守卫的使用

不管是history还是hash模式,路由守卫(比如beforeEach)的逻辑是一样的,但要注意:history模式下,pushState不会触发popstate事件(比如前进后退会触发),所以如果在守卫里处理页面跳转逻辑,要确保逻辑对所有路由变化生效,别只依赖特定事件。

SEO优化咋搞?

SPA的SEO天生弱,因为爬虫(比如百度、谷歌)爬取页面时,可能不执行JS,导致看不到前端渲染的内容,history模式下,想做SEO可以这么搞:

  • 服务端渲染(SSR):用Vue SSR把页面在服务器渲染成HTML,再返回给浏览器,比如Nuxt.js就是基于Vue的SSR框架,能解决SEO问题。
  • 预渲染(Prerender):用prerender-spa-plugin这类工具,在构建时生成每个路由的静态HTML文件,比如配置后,/about会生成about/index.html,爬虫能直接拿到内容。

举个预渲染的简单配置(Vue CLI项目):

// vue.config.js
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const path = require('path')
module.exports = {
  configureWebpack: () => {
    if (process.env.NODE_ENV === 'production') {
      return {
        plugins: [
          new PrerenderSPAPlugin({
            staticDir: path.join(__dirname, 'dist'),
            routes: ['/', '/about'], // 要预渲染的路由
          })
        ]
      }
    }
  }
}

这样构建后,dist目录下会生成每个路由的静态HTML,SEO友好度up~

404页面咋处理?

想做自定义404页面,得在路由配置里加通配符路由

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '*', component: NotFound } // 匹配所有未定义的路由
]

但注意:必须先配服务器转发,否则服务器返回404,根本到不了前端路由这一步,所以得先按前面讲的配好服务器,再加前端的404路由,这样用户访问不存在的路径时,才会显示自定义的NotFound组件。

常见问题Q&A

最后集中解答几个高频问题,帮你快速排雷~

Q1:history模式下,刷新页面报404,咋解决?

A:看部署部分的服务器配置,把所有请求转发到index.html,不同服务器配置方法不一样,Nginx、Apache、Node.js的配置前面都讲过,照着配就行。

Q2:IE9能跑history模式吗?

A:不行,因为history模式依赖HTML5 History API,而IE9及以下不支持这组API,如果要兼容IE9,只能用hash模式。

Q3:history模式下,能设置页面标题吗?

A:当然能!可以用路由守卫或者Vue Router的afterEach钩子,结合document.title设置。

router.afterEach((to) => {
  document.title = to.meta.title || '默认标题'
})
// 路由配置里加meta
{ path: '/about', component: About, meta: { title: '关于我们' } }

Q4:history模式下,能传参吗?和hash模式有区别吗?

A:传参方式和模式没关系~不管是params、query,还是动态路由(如/user/:id),用法都一样,比如用$router.push({ name: 'User', params: { id: 123 } }),URL会变成/user/123(history模式)或/#/user/123(hash模式)。

到这儿,Vue Router history模式的核心知识点就讲完啦~记住核心逻辑:它靠HTML5 History API实现美观URL,但部署要配服务器转发;和hash模式各有优劣,选的时候看项目需求,下次再遇到history模式的问题,回忆下这篇内容,应该能快速解决~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门