详解vue 单页应用(spa)前端路由实现原理

写在前面:通常 SPA 中前端路由有2种实现方式:

  1. window.history
  2. location.hash

下面就来介绍下这两种方式具体怎么实现的

一.history

1.history基本介绍

window.history 对象包含浏览器的历史,window.history 对象在编写时可不使用 window 这个前缀。history是实现SPA前端路由是一种主流方法,它有几个原始方法:

  1. history.back() - 与在浏览器点击后退按钮相同
  2. history.forward() - 与在浏览器中点击按钮向前相同
  3. history.go(n) - 接受一个整数作为参数,移动到该整数指定的页面,比如go(1)相当于forward(),go(-1)相当于back(),go(0)相当于刷新当前页面
  4. 如果移动的位置超出了访问历史的边界,以上三个方法并不报错,而是静默失败

在HTML5,history对象提出了 pushState() 方法和 replaceState() 方法,这两个方法可以用来向历史栈中添加数据,就好像 url 变化了一样(过去只有 url 变化历史栈才会变化),这样就可以很好的模拟浏览历史和前进后退了,现在的前端路由也是基于这个原理实现的。

2.history.pushState

pushState(stateObj, title, url) 方法向历史栈中写入数据,其第一个参数是要写入的数据对象(不大于640kB),第二个参数是页面的 title, 第三个参数是 url (相对路径)。

  1. stateObj :一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。
  2. title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。
  3. url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。

关于pushState,有几个值得注意的地方:

pushState方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应,只有当触发前进后退等事件(back()和forward()等)时浏览器才会刷新

这里的 url 是受到同源策略限制的,防止恶意脚本模仿其他网站 url 用来欺骗用户,所以当违背同源策略时将会报错

3.history.replaceState

replaceState(stateObj, title, url) 和pushState的区别就在于它不是写入而是替换修改浏览历史中当前纪录,其余和 pushState一模一样

4.popstate事件

定义:每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。

注意:仅仅调用pushState方法或replaceState方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。

用法:使用的时候,可以为popstate事件指定回调函数。这个回调函数的参数是一个event事件对象,它的state属性指向pushState和replaceState方法为当前URL所提供的状态对象(即这两个方法的第一个参数)。

5.history实现spa前端路由代码

<a class="api a">a.html</a>
<a class="api b">b.html</a>
 // 注册路由
  document.querySelectorAll('.api').forEach(item => {
   item.addEventListener('click', e => {
    e.preventDefault();
    let link = item.textContent;
    if (!!(window.history && history.pushState)) {
     // 支持History API
     window.history.pushState({name: 'api'}, link, link);
    } else {
     // 不支持,可使用一些Polyfill库来实现
    }
   }, false)
  });

  // 监听路由
  window.addEventListener('popstate', e => {
   console.log({
    location: location.href,
    state: e.state
   })
  }, false)

popstate监听函数里打印的e.state便是history.pushState()里传入的第一个参数,在这里即为{name: 'api'}

二.Hash

1.Hash基本介绍

url 中可以带有一个 hash http://localhost:9000/#/a.html

window 对象中有一个事件是 onhashchange,以下几种情况都会触发这个事件:

  1. 直接更改浏览器地址,在最后面增加或改变#hash;
  2. 通过改变location.href或location.hash的值;
  3. 通过触发点击带锚点的链接;
  4. 浏览器前进后退可能导致hash的变化,前提是两个网页地址中的hash值不同。

2.Hash实现spa前端路由代码

  // 注册路由
  document.querySelectorAll('.api').forEach(item => {
   item.addEventListener('click', e => {
    e.preventDefault();
    let link = item.textContent;
    location.hash = link;
   }, false)
  });

  // 监听路由
  window.addEventListener('hashchange', e => {
   console.log({
    location: location.href,
    hash: location.hash
   })
  }, false)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • vue中SPA单页面应用程序详解
(0)

相关推荐

  • vue中SPA单页面应用程序详解

    一.SPA的概述 SPA(single page application)单页面应用程序,在一个完成的应用或者站点中,只有一个完整的html页面,这个页面有一个容器,可以把需要加载的代码片段插入到该容器中. SPA的工作原理: eg:  http://127.0.0.1/index.html#/start ①根据地址栏中url解析完整的页面:index.html 加载index.html ②根据地址栏中url解析#后的路由地址: start 根据路由地址,去在当前应用的配置中 找该路由地址的配置

  • 详解vue 单页应用(spa)前端路由实现原理

    写在前面:通常 SPA 中前端路由有2种实现方式: window.history location.hash 下面就来介绍下这两种方式具体怎么实现的 一.history 1.history基本介绍 window.history 对象包含浏览器的历史,window.history 对象在编写时可不使用 window 这个前缀.history是实现SPA前端路由是一种主流方法,它有几个原始方法: history.back() - 与在浏览器点击后退按钮相同 history.forward() - 与

  • 详解VUE单页应用骨架屏方案

    什么是骨架屏? 简单的说,骨架屏就是在页面未渲染完成的时候,先用一些简单的图形大致勾勒出页面的基本轮廓,给用户造成页面正在加载的错觉,待页面渲染完成之后再用页面替换掉骨架屏,从而减少页面白屏的时间,给用户带来更好的体验. 分析VUE渲染过程 使用vue-cli3.0创建项目: vue create project 在生成的项目文件夹下的public文件夹下的index.html文件代码如下: <!DOCTYPE html> <html lang="en"> &l

  • 详解Vue 单文件组件的三种写法

    JS构造选项写法 export defaul { data, methods, ...} JS class写法 @Component export default class Cpn extends Vue{ counter = 0 //data add(){ //methods this.counter += 1 } } TS class写法 @Component export default class Cpn extends Vue{ @Prop(Number) sum : number

  • 详解vue数组遍历方法forEach和map的原理解析和实际应用

    一.前言 forEach和map是数组的两个方法,作用都是遍历数组.在vue项目的处理数据中经常会用到,这里介绍一下两者的区别和具体用法示例. 二.代码 1. 相同点 都是数组的方法 都用来遍历数组 两个函数都有4个参数:匿名函数中可传3个参数item(当前项), index(当前项的索引), arr(原数组),还有一个可选参数this 匿名函数中的this默认是指向window的 对空数组不会调用回调函数 不会改变原数组(某些情况下可改变) 2. forEach (1) 没有返回值. var

  • 详解vue 自定义组件使用v-model 及探究其中原理

    1.首先我们来实现自定义组件中使用v-model 父组件中注册子组件 <template> <div id="app"> <p>{{name}}</p> <MyInput v-model="name"/> </div> </template> <script> import MyInput from './components/MyInput.vue' export de

  • vue单页开发父子组件传值思路详解

    vue单页开发时经常需要父子组件之间传值,自己用过但是不是很熟练,这里我抽空整理了一下思路,写写自己的总结. GitHub地址:https://github.com/leileibrother/wechat-vue 文件目录如下图,example.vue是父组件,exampleChild.vue是子组件. 父组件引入子组件,父组件html的代码如下: <template> <div> <h3>这是父组件</h3> <p style="marg

  • 详解vue 表单绑定与组件

    一.什么是双向数据绑定 Vue.js是一个MV VM框架, 即数据双向绑定, 即当数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化.这也算是Vue.js的精髓之处了.   值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的非UI控件不会涉及到数据双向绑定.单向数据绑定是使用状态管理工具的前提.如果我们使用vue x那么数据流也是单项的,这时就会和双向数据绑定有冲突. 1.为什么要实现数据的双向绑定 在Vue.js中,如果使用vuex, 实际上数据还

  • 详解vue表单——小白速看

    一.基本用法 你可以用 v-model 指令在表单 <input> 及 <textarea> 元素上创建双向数据绑定. 但 v-model 本质上不过是语法糖.它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理. v-model 会忽略所有表单元素的 value.checked.selected 特性的初始值而总是将 Vue 实例的数据作为数据来源.你应该通过 JavaScript 在组件的 data 选项中声明初始值. 一组代码,看完text.textarea.

  • 详解Vue文档中几个易忽视部分的剖析

    针对Vue文档中部分大家可能不会去研读的内容,我做了个小总结,作为有经验者的快餐,不是特别适合初学者,可能有不妥之处,希望大家多提建议. 节省代码量的mixin mixin概念:组件级可复用逻辑,包括数据变量/生命周期钩子/公共方法,从而在混入的组件中可以直接使用,不用重复写冗余逻辑(类似继承) 使用方法: 在某一公共文件夹pub下创建mixin文件夹,其下创建mixinTest.js const mixinTest = { created() { console.log(`components

  • 详解Vue开发网站seo优化方法

    因为用了vue等js的数据绑定机制来展示页面数据,爬虫获取到的html是模型页面而不是最终数据的渲染页面,搜索引擎是不回去执行请求到的js.vue的项目都是ajax请求数据,引擎爬虫进入页面获取不到文字内容,现在大多数解决方案是不采用ajax渲染数据,而是采用server端渲染,也就是所谓的SSR. 目前基于vue的方案是Nuxt.js,同类型的也有React版的Nuxt.js所以服务端渲染就是尽量在服务器发送到浏览器前,页面上是有数据可让爬虫进行爬取 方法一.利用prerender-spa-p

随机推荐