vue-router路由模式详解

引用:https://www.cnblogs.com/goloving/p/9147551.html

一、路由模式解析

要讲vue-router的路由模式,首先要了解的一点就是路由是由多个URL组成的,使用不同的URL可以相应的导航到不同的位置。

如果有进行过服务器开发或者对http协议有所了解就会知道,浏览器中对页面的访问是无状态的,所以我们在切换不同的页面时都会重新进行请求。而实际使用vue和vue-router开发就会明白,在切换页面时是没有重新进行请求的,使用起来就好像页面是有状态的,这是什么原因呢。

这其实是借助了浏览器的History API来实现的,这样可以使得页面跳转而不刷新,页面的状态就被维持在浏览器中了。

vue-router中默认使用的是hash模式,也就是会出现如下的URL:
image

,URL中带有#号

我们可以用如下代码修改成history模式

import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/components/Main'
Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      component: Main
    }
  ]
})

这样子URL中的#号就被去除了。

实际上存在三种模式:

Hash: 使用URL的hash值来作为路由。支持所有浏览器。

History: 以来HTML5 History API 和服务器配置。参考官网中HTML5 History模式

Abstract: 支持所有javascript运行模式。如果发现没有浏览器的API,路由会自动强制进入这个模式。

二、两种模式的区别

1、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;
}

上面的代码可以通过改变hash来改变页面字体颜色,虽然没什么用,但是一定程度上说明了原理。

更关键的一点是,因为hash发生变化的url都会被浏览器记录下来,从而你会发现浏览器的前进后退都可以用了,同时点击后退时,页面字体颜色也会发生变化。这样一来,尽管浏览器没有请求服务器,但是页面状态和url一一关联起来,后来人们给它起了一个霸气的名字叫前端路由,成为了单页应用标配。

我们写个简单的方法来测试一下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>测试一下</div>
    <script type="text/javascript">
        window.onhashchange = function(event){
            console.log(event.oldURL,event.newURL)
            let hash = location.hash.slice(1);
            document.body.style.color = hash;
        }
    </script>
</body>
</html>
image
image

并且通过浏览器的前进、后退页面均可以变化。

网易云音乐,百度网盘就采用了hash路由,看起来就是这个样子:

http://music.163.com/#/friend
https://pan.baidu.com/disk/home#list/vmode=list

2、history路由

随着history api的到来,前端路由开始进化了,前面的hashchange,你只能改变#后面的url片段,而history api则给了前端完全的自由

history api可以分为两大部分:切换和修改

(1)切换历史状态

包括back、forwardgo三个方法,对应浏览器的前进,后退,跳转操作,有同学说了,(谷歌)浏览器只有前进和后退,没有跳转,嗯,在前进后退上长按鼠标,会出来所有当前窗口的历史记录,从而可以跳转(也许叫跳更合适):

history.go(-2);//后退两次
history.go(2);//前进两次
history.back(); //后退
hsitory.forward(); //前进

(2)修改历史状态

包括了pushState、replaceState两个方法,这两个方法接收三个参数:stateObj,title,url

[
复制代码

](javascript:void(0); "复制代码")

history.pushState({color:'red'}, 'red', 'red')

window.onpopstate = function(event){
    console.log(event.state)
    if(event.state && event.state.color === 'red'){
        document.body.style.color = 'red';
    }
}

history.back();

history.forward();

通过pushstate把页面的状态保存在state对象中,当页面的url再变回这个url时,可以通过event.state取到这个state对象,从而可以对页面状态进行还原,这里的页面状态就是页面字体颜色,其实滚动条的位置,阅读进度,组件的开关的这些页面状态都可以存储到state的里面。

通过history api,我们丢掉了丑陋的#,但是它也有个毛病:

不怕前进,不怕后退,就怕刷新f5,(如果后端没有准备的话),因为刷新是实实在在地去请求服务器的。

在hash模式下,前端路由修改的是#中的信息,而浏览器请求时是不带它玩的,所以没有问题。但是在history下,你可以自由的修改path,当刷新时,如果服务器中没有相应的响应或者资源,会分分钟刷出一个404来。

(3)popstate实现history路由拦截,监听页面返回事件

当活动历史记录条目更改时,将触发popstate事件。

1、如果被激活的历史记录条目是通过对 history.pushState() 的调用创建的,或者受到对 history.replaceState() 的调用的影响,popstate事件的state属性包含历史条目的状态对象的副本。

2、需要注意的是调用 history.pushState() 或 history.replaceState() 用来在浏览历史中添加或修改记录,不会触发popstate事件;

只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back())

我们测试一下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>测试一下</div>
    <script type="text/javascript">
        if (window.history && window.history.pushState) {
           window.onpopstate = function(event) {
              console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
              //window.history.go(1)
              //window.history.back()
           };
         
           //window.addEventListener("popstate", function(e) {
           //   window.location = 'http://www.baidu.com';
           //}, false);
         
           !function() {
              var state = {
                 title: "title",
                 url: "#"
              };
              window.history.pushState(state, "title", "#");
           }();
        }
    </script>
</body>
</html>

刷新时不打印,刷新多次,再后退,每次都有,直到为null

image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354