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

众所周知,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. 使用7-zip进行分卷压缩和解分卷压缩(Windows和Linux)

    现在一共有10个视频,一共313M,我对该文件夹进行分卷压缩,每个tar包100M,压缩过程如下: Windows环境首先选中所有的压缩包,然后在压缩包上单击鼠标右键,然后选择7-Zip,再选择提取到 ...

  2. 思维分析逻辑 4 DAY

    目录 竞品分析 波特五力模型 竞品分析步骤 分析目的 对比分析 初步结论 活动营销分析 用户增长分析 用户增长基本模型 渠道思维(前期) 用户思维(中期) ROI思维(后期) 增长思维 北极星指标:一 ...

  3. Linux中出现Perf: interrupt took too long

    问题原因: perf: interrupt took too long_雪虎-JL的博客-CSDN博客 解决方法: perf: interrupt took too long (3136 > 3 ...

  4. 内核5.4以上, Realtek 8111网卡初始化失败

    在Centos7中, 升级内核到5.4.x或5.11.x时, 都会出现realtek8111网卡无法启动的问题, 在dmesg中能看到这个错误 $ dmesg |grep -i r8169 ... r ...

  5. Linux 下配置Oracle开机自动启动

    一./etc/oratab说明 直接使用cat 查看这个文件: gg1:/home/oracle> cat /etc/oratab # # This file is used by ORACLE ...

  6. js与java使用AES加密算法实现前后端加密解密

    AES加密算法入门:https://blog.csdn.net/IndexMan/article/details/87284833 第三方crypto.js下载地址:https://download. ...

  7. Java I/O 教程(九) FileWriter和FileReader

    FileWriter Java FileWriter 用于往文件中写入字符数据. 不像FileOutputStream类,你无需转换字符串成字节数组,因为它提供了直接写字符串的方法. 类定义 publ ...

  8. 编译 windows 上的 qt 静态库

    记录命令行编译过程: 针对 Qt 5.15.2 版本, 只需要 Source 文件就行 打开 x86 Native Tools Command Prompt for VS 2019,如果需要编译 x6 ...

  9. golang常用库包:redis操作库go-redis使用(03)-高级数据结构和其它特性

    Redis 高级数据结构操作和其它特性 第一篇:go-redis使用,介绍Redis基本数据结构和其他特性,以及 go-redis 连接到Redis https://www.cnblogs.com/j ...

  10. 【Android逆向】滚动的天空中插入smali日志

    1. 编写一个MyLog.java 放到一个android工程下,编译打包,然后反编译拿到MyLog的smali代码 package com.example.logapplication; impor ...