这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

众所周知,vue路由模式常见的有 historyhash 模式,但其实还有一种方式-abstract模式(了解一哈~)

别急,本文我们将重点逐步了解: 路由 + 几种路由模式 + 使用场景 + 思考 + freestyle


路由概念

路由的本质就是一种对应关系,根据不同的URL请求,返回对应不同的资源。那么url地址和真实的资源之间就有一种对应的关系,就是路由。


路由模式由来

对于 Vue 这类渐进式前端开发框架,为了构建 SPA(单页面应用),需要引入前端路由系统,这也就是 Vue-Router 存在的意义。而前端路由的核心,就在于 —— 改变视图的同时不会向后端发出请求

为了达到这一目的,就产生了我们的 —— 路由模式


三种路由模式详解


hash模式

示例: www.ikun.com/#/kun,hash 的值为 #/kun。

概述:

地址栏 URL 中有 # 符号,后面就是 hash 值的变化(此 hash 不是密码学里的散列运算)。特点是:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端没有影响,改变后面的 hash 值,它不会向服务器发出请求,因此也就不会 刷新页面/重新加载页面

每次 hash 值发生改变的时候,会触发 hashchange 事件。因此我们可以通过监听该事件,来知道 hash 值发生了哪些变化。

window.addEventListener('hashchange', ()=>{
// 通过 location.hash 获取到最新的 hash 值
   console.log(location.hash);
});

使用:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>hash路由</title>
</head>
<body>

 <ul>
   <!-- 通过标签导航 声明式导航 -->
   <!-- location.href='#/home' js方式进行导航切换 编程式导航 -->
   <li><a href="#/home">首页</a></li>
   <li><a href="#/about">关于</a></li>
 </ul>

 <div id="routerView"></div>

 <script>
   const routerRender = () => {
     // 每次都置空hash
     let html = ''
     // 根据地址栏hash值的不同返回对应的资源
     try {
       // 如果hash值为空就给一个home
       let hash = location.hash || '#/home'
       html = component[hash.slice(2)]()
    } catch (error) {
       html = `<div>404</div>`
    }
     // 渲染到页面上
     document.getElementById('routerView').innerHTML = html
  }

   const component = {
     home() {
       return `<div>home页面</div>`
    },
     about() {
       return '<div>关于页面</div>'
    }
  }

   window.onload = function () {
     routerRender()
  }

   // 事件,监听地址栏中的hash值变化,实现回退
   window.addEventListener('hashchange', routerRender)
     
 </script>
</body>
</html>

优缺点:

优点:hash模式兼容性、安全性很强,刷新浏览器,页面还会存在

缺点:地址栏不优雅,有#存在,不利于seo,记忆困难

注意:

hash 模式既可以通过声明式导航,也可以通过编程式导航,上面的案例展示的是声明式导航。而下面将要讲到的 history 模式只能通过编程式导航实现,因为 history 是 js 对象。


history模式

示例: www.ikun.com/kun,地址栏中没有#,路由地址跟正常的url一样

概述:

history —— 利用了 HTML5 History API 为浏览器的全局 history 对象增加的 pushState()replaceState() 方法,可以对浏览器历史记录栈进行修改。(新增特性,所以浏览器需考虑IE9以及以下的版本带来的问题)。当地址栏的history状态发生变化时 切换了router-view渲染的组件 来"欺骗"用户 到达切换新网页的效果,需要后端配合

History 还包括back、forward、go三个方法,对应浏览器的前进,后退,跳转操作。就是浏览器左上角的前进、后退等按钮进行的操作。

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

只要历史栈有信息发生改变的话,window对象中提供的 popstate 事件就会监听到历史栈的改变,就会触发该事件。

history.pushState({},title,url); // 向历史记录中追加一条记录
history.replaceState({},title,url); // 替换当前页在历史记录中的信息。

window.addEventListener('popstate', function(e) {
 console.log(e)
})

使用:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>history模式</title>
</head>

<body>
 <ul>
   <li><a href="/home">首页</a></li>
   <li><a href="/about">关于</a></li>
 </ul>

 <div id="routerView"></div>

 <script>
   const component = {
     home() {
       return `<div>home页面</div>`
    },
     about() {
       return '<div>关于页面</div>'
    }
  }

   const routerRender = pathname => {
     let html = ''
     try {
       html = component[pathname]()
    } catch (error) {
       html = `<div>404</div>`
    }
     document.getElementById('routerView').innerHTML = html
  }

   // history模式,它的路由导航,只能通过js来完成 , history它是js对象
   // 给链接添加点击事件
   document.querySelectorAll('a').forEach(node => {
     node.addEventListener('click', function (evt) {
       // 阻止a标签的默认跳转行为
       evt.preventDefault()
       // 跳转到指定的地址,能回退
       // history.pushState
       // 跳转到指定持址,不能回退
       // history.replaceState
       history.pushState({}, null, this.href)
       // 渲染
       routerRender(this.href.match(//(\w+)$/)[1])
    })
  })

   // 在网页加载完毕后立刻执行的操作,即当 HTML 文档加载完毕后,立刻渲染 home 中的标签
   window.onload = () => {
     routerRender('home')
  }

   // 回退
   window.addEventListener('popstate', function () {
     routerRender(location.pathname.slice(1))
  })

 </script>
</body>
</html>

优缺点:

缺点:history模式,兼容性较差,刷新页面,页面会404,需要服务器端配置支持

优点:地址栏更优雅,方便记忆,有利于有seo


刷新页面出现404原因以及解决:

原因:

因为vue项目中路由hash模式改为了history模式,由于hash模式时url带的#号后面是哈希值不会作为url的一部分发送给服务器,而history模式下当刷新页面之后浏览器会直接去请求服务器,而服务器没有这个路由,于是就出现404

因为我们的应用是单页客户端应用,当使用 history 模式时,URL 就像正常的 url,可以直接访问www.ikun.com/kun/love,但是因为 vue-router 设置的路径不是真实存在的路径,所以刷新就会返回404错误

解决方法(后端配合,这里讲的是nginx配置):

在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。也就是在服务端修改404错误页面的配置路径,让其指向到index.html

方法一:

    location /{
       root   /data/nginx/html;
       index  index.html index.htm;
       if (!-e $request_filename) {
           rewrite ^/(.*) /index.html last;
           break;
      }
  }

方法二: (vue.js官方教程里提到的https://router.vuejs.org/zh-cn/essentials/history-mode.html)

  server {
      listen       8888;#默认端口是80,如果端口没被占用可以不用修改
      server_name localhost;
      root       E:/vue/my_project/dist;#vue项目的打包后的dist
      location / {
          try_files $uri $uri/ @router;#需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
          index index.html index.htm;
      }
      #对应上面的@router,主要原因是路由的路径资源并不是一个真实的路径,所以无法找到具体的文件
      #因此需要rewrite到index.html中,然后交给路由在处理请求资源
      location @router {
          rewrite ^.*$ /index.html last;
      }
      #.......其他部分省略
}

abstract模式

abstract模式----适用于所有JavaScript环境,例如服务器端使用Node.js。如果没有浏览器API,路由器将自动被强制进入此模式。

abstract 是一种与浏览器分离的路由模式,本身是用来在不支持浏览器API的环境中,充当fallback,而不论是hash还是history模式都会对浏览器上的url产生作用。

利用abstract这种与浏览器分离的路由模式,我们可以在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由path。


使用场景


history --- 颜值性(强迫症患者推荐,更友好的URL格式、SEO支持)

一般场景下,hash 和 history 都可以,除非你更在意颜值,# 符号夹杂在 URL 里看起来确实有些不太美丽。我们可以用路由的 history 模式,充分利用 history.pushState API 来完成URL 跳转而无须重新加载页面。如果需要更好的SEO支持,并且愿意进行服务器端配置,history 模式是很好的选择

调用 history.pushState() 相比于直接修改 hash,还存在以下优势

1、pushState() 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 #后面的部分,因此只能设置与当前 URL 同文档的 URL;

2、pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash设置的新值必须与原来不一样才会触发动作将记录添加到栈中;

3、pushState() 通过 stateObject 参数可以添加任意类型的数据到记录中;而 hash 只可添加短字符串;

4、pushState() 可额外设置 title 属性供后续使用。

hash ---- 安全兼容,不需要后端协助

SPA 虽然在浏览器里游刃有余,但真要通过 URL 向后端发起 HTTP 请求时,两者的差异就来了。尤其在用户手动输入 URL 后回车,或者刷新(重启)浏览器的时候

hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 www.ikun.com ,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误

abstract模式 ---- 特殊场景

abstract模式----适用于所有JavaScript环境(浏览器端和服务端),例如服务器端使用Node.js。

像上文说的,可以利用abstract这种与浏览器分离的路由模式,在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由path。


小结


选择使用 hash 模式还是 history 模式,主要取决于你的具体需求和项目要求。如果你的应用不需要考虑SEO,并且不涉及服务器端的重定向和处理,Hash模式是一种简单且易于使用的选择。如果你需要更友好的URL格式、更好的SEO支持,并且愿意进行服务器端配置,那么history 模式是更好的选择。

结合自身例子,对于一般形式的 Web 开发场景,个人比较习惯用用 history 模式,只需在后端(Apache 或 Nginx)进行简单的路由配置,同时搭配前端路由的 404 页面支持。

本文转载于:

https://juejin.cn/post/7297035708429484066

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--啊?Vue是有三种路由模式的?的更多相关文章

  1. vue切换路由模式{hash/history}

    vue中常用的路由模式 hash(#):默认路由模式 histroy(/)切换路由模式 切换路由模式 export default new Router({ // 路由模式:hash(默认),hist ...

  2. vue 中的路由为什么 采用 hash 路由模式,而不是href超链接模式(Hypertext,Reference)?

    1. vue中路由模式的种类有两种 1. 一种是 hash 模式. 2. 一种是 h5 的 history 模式. 2. hash 和 history 都是来自 bom 对象 bom 来自 windo ...

  3. vue-router路由模式

    什么是单页应用? 单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web ...

  4. vue-router路由模式详解

    一.路由模式解析 要讲vue-router的路由模式,首先要了解的一点就是路由是由多个URL组成的,使用不同的URL可以相应的导航到不同的位置. 如果有进行过服务器开发或者对http协议有所了解就会知 ...

  5. Vue-router(前端路由)的两种路由模式

    Vue的两种路由模式: hash.history:默认是hash模式: 前端路由(改变视图的同时不会向后端发出请求) 一.什么是hash模式和history模式? hash模式:是指url尾巴后的#号 ...

  6. RabbitMQ六种队列模式-路由模式

    前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主 ...

  7. Vue的hash/history模式

    hash路由模式 URL 中的 hash 值只是客户端的一种状态,向服务端发送请求的时候,hash 部分不会被发送: hash 值得改变会在浏览器的历史记增加访问记录,所以可以通过浏览器的回退.前进控 ...

  8. 修改thinkphp路由模式,去掉Home

    第一步:入口文件增加 define('BIND_MODULE', 'Home'); 第二步:修改config文件,我这里路由模式设置为2 效果展示:

  9. RabbitMQ 一二事(4) - 路由模式介绍

    路由模式其实和订阅模式差不多,只不过交换机的类型不同而已 路由模式可以用下图来表示,比订阅模式多了一个key,举个栗子就是根据不同的人群来订阅公众号,来收取消息 根据不同的key来获取不同的消息 最简 ...

  10. php有三种工作模式

    php有三种工作模式. 其中是最常见的是php作为一个模块工作在一个多进程的webserver中, 例如apache webserver. apache会启动一个主进程, 多个子进程(php). 主进 ...

随机推荐

  1. Pandas日期时间格式化

    当进行数据分析时,我们会遇到很多带有日期.时间格式的数据集,在处理这些数据集时,可能会遇到日期格式不统一的问题,此时就需要对日期时间做统一的格式化处理.比如"Wednesday, June ...

  2. JS 保姆级贴心,从零教你手写实现一个防抖debounce方法

    壹 ❀ 引 防抖在前端开发中算一个基础但很实用的开发技巧,在对于一些高频操作例如监听输入框值变化触发更新之类,会有奇效.除了实际开发,在面试中我们也可能偶遇手写防抖节流的问题,鉴于不同公司考核要求不一 ...

  3. mc命令

    mc命令 mc是一个基于字符的目录浏览器和文件管理器,其将熟悉的图形文件管理器和常见的命令行工具联系在一起,mc的设计基于文件管理器中双目录窗格的设计,其中同时显示两个目录的列表,可以执行所有常见的文 ...

  4. spring boot与junit集成测试

    先创建一个REST接口 package com.laoxu.gamedog.controller; import org.springframework.web.bind.annotation.Req ...

  5. Ubuntu 安装 Python3.6.7

    注意: 不要卸载ubuntu自带的python版本: ubuntu下不同版本的python可以共存,可直接安装python3.6. 1.升级包索引和软件 sudo apt update sudo ap ...

  6. 记录一个错误:Traceback (most recent call last): from pip._internal.cli.main import main ImportError: No module named pip._internal.cli.main

    问题描述 在安装yaml时得到报错如下 root@ag-virtual-machine:/home/ag/test_script# pip install pyyaml Traceback (most ...

  7. 【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压

    问题描述 消费型逻辑应用(Consumption Logic App)使用触发器模式消费 Azure Service Bus的消息,当Service Bus中存在大量消息等待消费时,Logic App ...

  8. 【Azure 应用服务】使用Docker Compose创建App Service遇见"Linux Version is too long. It cannot be more than 4000 characters"错误

    问题描述 使用Docker Compose方式合并多个镜像(Images)文件,然后部署到App Service中,结果失败.报错 Linux Version 太长,不能超过4000个字符. 错误消息 ...

  9. 【Azure 服务总线】Azure门户获取ARM模板,修改Service Bus的TLS版本

    问题描述 在Azure中创建Sverice Bus服务后,如果想修改服务的TLS版本,是否有办法呢? 问题解答 通过Service Bus的ARM模板,修改属性值中的 minimumTlsVersio ...

  10. 图数据库实操:用 Nebula Graph 破解成语版 Wordle 谜底

    本文首发于 Nebula Graph Community 公众号 春节期间如果有小伙伴玩过 Wordle 这个火爆社交媒体的猜词游戏,可能对成语版本的汉兜有所耳闻.在玩汉兜过程中,我发现用 Nebul ...