vue路由的两种模式mode:hash和history

2,326 阅读3分钟

一、vue是什么

vue是一种单页应用(SPA),单页应用就是仅在页面初始化的时候加载相应的html/css/js,单页面加载完成后,不会因为用户的操作进行页面的重新加载或者跳转,而是用js动态的变化html的内容。

优点:页面很流畅,具有良好的交互体验,用户不需要刷新页面,且是前后端工作分离的模式,可以减轻福服务器压力。

二、hash和history

1.hash模式

hash模式url带#号,比如这个URL:www.abc.com/#/hello, hash 的值为#/hello。vue-router默认的是hash模式---使用URL的hash来模拟一个完整的URL,于是当URL改变的时候,页面不会重新加载,也就是单页应用,当#后面的hash值发生变化,不会导致浏览器向服务器发出请求,浏览器不发出请求就不会刷新页面,并且会触发hashChange这个事件,通过监听hash值的变化来实现更新页面部分内容的操作。

hash模式的原理是onhashchange事件,可以在window对象上监听这个事件:

window.onhashchange = function(event){
    console.log(event.oldURL, event.newURL);
    let hash = location.hash.slice(1);
    document.body.style.color = hash;
}

2.history模式

history模式不带#号。利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法(需要特定浏览器支持),pushState()可以改变url地址且不会发送请求,replaceState()可以读取历史记录栈,还可以对浏览器记录进行修改。这两个方法应用于浏览器的历史记录站,在当前已有的back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改是,虽然改变了当前的URL,但你浏览器不会立即向后端发送请求。

window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
区别
  • hashChange只能改变#后面的url片段。而pushState设置的新的URL可以是与当前URL同源的任意URL。
  • history模式则会将URL修改得和正常请求后端的URL一样,如果后端没有配置对应的/movie/id的路由处理,则会返回404错误。

PS:当用户刷新页面之类的操作时,浏览器会给服务器发送请求,所有这个实现需要服务器的支持,需要把所有路由重新定向到根页面。即history模式,会出现404 的情况,需要后台配置

关于404错误:

处理404的方法: 使用history模式时,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok了。

路由模式的配置:

export default new Router({
    mode: 'history',
    //mode: 'hash',
    routes
})

若是history模式需要后台配合解决刷新404问题,这里以Node后台为例:

const Koa = require('koa')
const Router = require('koa-router');
const static = require('koa-static')
const fs = require('fs');//node
const app = new Koa();
const router = new Router();

let str;
fs.readFile('../dist/index.html', "utf-8", (err, data) => {
    if (err) {
        ctx.body = "error found"
    }
    str = data.toString();
})

// 解决vue 路由在 history刷新 404情况
router.get('*', async(ctx, next) => {
    if (ctx.url !== "/index.html") {
        console.log("在这里返回")
        ctx.body = str;
    } 
})

app.use(static("../dist/"));
app.use(router.routes()) //启动路由
app.use(router.allowedMethods());

app.listen(8089, () => {
    console.log("监听服务器地址:127.0.0.1:8089");
})

谈到路由router的两种mode,就会涉及到url地址;首先得知道routerrouter与route的区别:

  • routerVueRouter实例。想要导航到不同的URL,则使用router为VueRouter实例。想要导航到不同的URL,则使用router.push()方法;返回上一个history使用$router.go()方法。
  • $route从当前对象router跳转对象里面可以获取name、path、query、params等。
* <router-link>传的参数由this.$route.query或者this.$route.params接收