详解从Vue-router到html5的pushState

最近在用vue的时候突然想到一个问题

首先,我们知道vue实现的单页应用中一般不会去刷新页面,因为刷新之后页面中的vuex数据就不见了。

其次,我们也知道一般情况下,url变更的时候,比如指定location.href、history.push、replace等,页面就会刷新。

那么问题来了,vue页面的页面跳转时怎么实现的?没刷新页面么?没刷新页面,又要改变url,加载新内容怎么做的?

去翻了一下vue-router的源码,找到这样一段

export class HTML5History extends History {
  ...

 push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  const { current: fromRoute } = this
  this.transitionTo(location, route => {
   pushState(cleanPath(this.base + route.fullPath))
   handleScroll(this.router, route, fromRoute, false)
   onComplete && onComplete(route)
  }, onAbort)
 }

 replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  const { current: fromRoute } = this
  this.transitionTo(location, route => {
   replaceState(cleanPath(this.base + route.fullPath))
   handleScroll(this.router, route, fromRoute, false)
   onComplete && onComplete(route)
  }, onAbort)
 }
 ...
}

再看看方法内部

export function pushState (url?: string, replace?: boolean) {
 saveScrollPosition()
 // try...catch the pushState call to get around Safari
 // DOM Exception 18 where it limits to 100 pushState calls
 const history = window.history
 try {
  if (replace) {
   history.replaceState({ key: _key }, '', url)
  } else {
   _key = genKey()
   history.pushState({ key: _key }, '', url)
  }
 } catch (e) {
  window.location[replace ? 'replace' : 'assign'](url)
 }
}

答案就是html5在history中新增加的方法:pushState和replaceState。这两个又是干啥的呢?(两个十分类似,以下以pushState为例说明,区别和push与replace一致)

HTML5的pushState()

首先看看这个是干什么的

pushState方法就是向history中push一条记录,更改页面url,但是不刷新页面,不刷新页面,不刷新页面。不刷新页面,这点很关键,这和下面的操作很相似

window.location.href = window.location.href + '#a=b'

知道干嘛的了,再看看API怎么用的

history.pushState(state, title, url);

state是一个对象,具体内容除了最大640KB之外没有别的限制,比如在vue中是生成了一个key存进去了。若无特殊需要传个null即可。这个state可以在history或者popstate的事件中看到

history中的

popstate中的

title这个参数目前没什么用处,可能是给以后预留的参数,暂时用null就好了

url很明显,就是替换后的url了。url可以接受绝对地址和相对地址,设置绝对地址的时候,要保证域名和当前域名一致,否则汇报如下错误

Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'https://www.baidu.com/' cannot be created in a document with origin 'https://mocard-aliyun1.chooseway.com:8443' and URL 'https://mocard-aliyun1.chooseway.com:8443/views/h5/indexasdasd'.
at History.pushState (https://aixuedaiimg.oss-cn-hangzhou.aliyuncs.com/static/m/js/alog/v1.0.0/alog.min.js:1:23259)
at <anonymous>:1:9

HTML5的popstate()

popstate与pushState相对应,主要在页面url变更的时候触发,一般绑定在window对象下

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

前面pushState中传入的state对象,可以在这边接收到,并根据需要去做一些处理。

说到这,vue-router是怎么实现页面“刷新”但不刷新的就知道了吧。

vue-router就是利用pushState这个属性,在页面前进的时候动态改变history的内容,添加一条记录,接着location跟着改变。同时根据router前往的路由获取对应的js资源文件并挂载到目标dom上实现页面内容的更新,但是页面本身并没有刷新。

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

(0)

相关推荐

  • vue-router 源码之实现一个简单的 vue-router

    前言 通过上篇,我们知道前端理由的两种实现方法,Hash 路由与 History 路由,并且用它们分别实现了一个前端路由. 接下来我们就将 Vue 与 Hash 路由结合,实现一个非常简单的 vue-router 吧. 开始实现 想象一下,如果自己实现了一个 vue-router,会怎么去使用呢?参考 vue-router 官方的使用方式,看看 html 的使用: <div id="app"> <p> <router-link to="#/&qu

  • vue-router中的hash和history两种模式的区别

    众所周知,vue-router有两种模式,hash模式和history模式,这里来谈谈两者的区别. hash模式 hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事件: window.onhashchange = function(event){ console.log(event.oldURL, event.newURL); let hash = location.hash.slice(1); document.body.style.color = has

  • 使用vue-router beforEach实现判断用户登录跳转路由筛选功能

    在开发webApp的时候,考虑到用户体验,经常会把不需要调用个人数据的页面设置成游客可以访问,而当用户进入到一些需要个人数据的,例如购物车,个人中心,我的钱包等等,在进行登录的验证判断,如果判断已经登录,则显示页面,如果判断未登录,则直接跳转到登录页面提示用户登录,今天就来分享下如何使用vue-router的beforEach方法来实现这个需求. 实现 本篇文章默认您已经会使用 webpack 或者 vue-cli 来进行环境的搭建,并且具有一定的vue基础,如果您目前是一个新手,那么网上搜索一

  • vue系列之requireJs中引入vue-router的方法

    requireJs简介 参数配置 requireJS 常用的方法与命令也就两个,因此requireJS使用起来非常简单. require define 其中define是用于定义模块,而require是用于载入模块以及载入配置文件. define([id,deps,] callback); require(deps[,callback]); 加载配置文件 独立的引入配置文件也有两种方式,一种是通过script标签加载外部JS文件形式: <script src="js/require.js&

  • 使用vue-router完成简单导航功能【推荐】

    vue-router是Vue.js官方提供的一套专用的路由工具库 安装命令如下 npm i vue-router -D vue-router 实例是一个Vue插件,我们需要在Vue全局引用中通过Vue.use() 将它接入到Vue实例中. 在我们的工程中,,main.js是默认的程序入口文件,所有的全局配置都会在这个文件中进行. 我们在main.js中加入如下引用 import VueRouter from 'vue-router' Vue.use(VueRouter) 这样就完成了 vue-r

  • vue-router中scrollBehavior的巧妙用法

    问题:使用keep-alive标签后部分安卓机返回缓存页位置不精确问题 解决方案: <div id="app"> <keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></

  • vue-router+nginx 非根路径配置方法

    vue-router 的默认数据hash模式-使用url的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载. 一般情况下,我们不喜欢丑丑的hash,类似于index.html#/matchResult,可以使用路由的history模式.history模式是利用history.pushState API来实现页面跳转. 但是有个问题,在使用nginx的时候,我们需要添加一些配置. 直接配置在根路径下 直接配置在根路径下,访问的时候只用输入http://yoursite.com,

  • vue-router history模式下的微信分享小结

    背景 旧项目改造,进行前后端分离.做成了spa,为了保证后端路由时期链接可用性,使用了history模式. 因为不同的页面有不同的分享内容,所以每次路由都要重新进行wx.config/wx.ready调用 微信分享遇到的坑 微信官方文档上有下面一段话: 所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushSt

  • vue-router 源码实现前端路由的两种方式

    在学习 vue-router 的代码之前,先来简单了解一下前端路由. 前端路由主要有两种实现方法: Hash 路由 History 路由 先来看看这两种方法的实现原理. 接着我们将用它们来简单实现一个自己的前端路由. 前端路由 Hash 路由 url 的 hash 是以 # 开头,原本是用来作为锚点,从而定位到页面的特定区域.当 hash 改变时,页面不会因此刷新,浏览器也不会向服务器发送请求. http://www.xxx.com/#/home 同时, hash 改变时,并会触发相应的 has

  • 详解使用Vue Router导航钩子与Vuex来实现后退状态保存

    不好意思,标题比较啰嗦,因为这次的流水账确实属于一个比较细节的小东西,下面详细讲: 1需求 最近在使用electron-vue开发一个跨平台的桌面端软件,刚上手写了几个页面,遇到一个问题:桌面端软件通常会有导航需求,类似下图 导航按钮 点击返回按钮,返回上一页,并且显示上页内容.其实不止App,即使普通的网页中也会有此类需求,尤其是使用vue写SPA时. 项目中的导航几乎都是采用router.push({name: 'xxx', params: {xxx:123...}})这种方式.这种方式导致

  • 详解本地Vue项目请求本地Node.js服务器的配置方法

    目录 1.使用vue-cli脚手架搭建vue项目 2.使用koa搭建node后端 3.Vue项目中添加后端请求 参考资料: 前言:本文只针对自己需要本地模拟接口于是搭建一个本地node服务器供自己测试使用,仅作自己从头到尾搭建项目的记录 1.使用vue-cli脚手架搭建vue项目 1.在桌面运行 cmd,使用命令vue create demo创建一个vue项目demo,插件依赖等使用默认配置2.项目创建成功之后,使用命令 cd demo,进入 demo 文件夹,然后使用命令 npm run se

  • 详解为什么Vue中不要用index作为key(diff算法)

    前言 Vue 中的 key 是用来做什么的?为什么不推荐使用 index 作为 key?常常听说这样的问题,本篇文章带你从原理来一探究竟. 另外本文的结论对于性能的毁灭是针对列表子元素顺序会交换.或者子元素被删除的特殊情况,提前说明清楚,喷子绕道. 本篇已经收录在 Github 仓库,欢迎 Star: https://github.com/sl1673495/blogs/issues/39 示例 以这样一个列表为例: <ul> <li>1</li> <li>

  • 详解在Vue.js编写更好的v-for循环的6种技巧

    在VueJS中,v-for循环是每个项目都会使用的东西,它允许您在模板代码中编写for循环. 在最基本的用法中,它们的用法如下. <ul> <li v-for='product in products'> {{ product.name }} </li> </ul> 但是,在本文中,我将介绍六种方法来使你的 v-for 代码更加精确,可预测和强大. 让我们开始吧. 1.始终在v-for循环中使用key 首先,我们将讨论大多数Vue开发人员已经知道的常见最佳做

  • 详解实现vue的数据响应式原理

    这篇文章主要是给不了解或者没接触过 vue 响应式源码的小伙伴们看的,其主要目的在于能对 vue 的响应式原理有个基本的认识和了解,如果在面试中被问到此类问题,能够知道面试官想让你回答的是什么?「PS:文中如有不对的地方,欢迎小伙伴们指正」 响应式的理解 响应式顾名思义就是数据变化,会引起视图的更新.这篇文章主要分析 vue2.0 中对象和数组响应式原理的实现,依赖收集和视图更新我们留在下一篇文章分析. 在 vue 中,我们所说的响应式数据,一般指的是数组类型和对象类型的数据.vue 内部通过

  • 详解Django+Vue+Docker搭建接口测试平台实战

    一. 开头说两句 大家好,我叫林宗霖,是一位测试工程师,也是全栈测开训练营中的一名学员. 在跟着训练营学习完Docker容器技术系列的课程后,理所应当需要通过实操来进行熟悉巩固.正好接口自动化测试平台需要迁移到新的测试服务器上,就想要体验一番Docker的"一次构建,处处运行".这篇文章简单介绍了下这次部署的过程,其中使用了Dockerfile定制镜像和Docker-Compose多容器编排. 二. 项目介绍 项目采用的是前后端分离技术来实现的,前端是Vue+ElementUI,后端是

  • 详解基于Vue cli开发修改外部组件Vant默认样式

    前言 在引入外部组件的时候,想要修改默认样式,可以通过class修改,但一般会有权重不够等各种原因,官网其实列出了一套主题定制的方案,通过覆盖配置文件来修改样式,官网地址:主题定制 提示:以下是本篇文章正文内容,下面案例可供参考 一.Less 因为Vant 使用了 Less 对样式进行预处理,并内置了一些样式变量,可以通过替换样式变量即可定制你自己需要的主题. 给你的项目配置less: npm install less --save-dev npm install less-loader --s

  • 详解在vue使用weixin-js-sdk常见使用方法

    链接:https://qydev.weixin.qq.com/wiki/index.php?title=%E5%BE%AE%E4%BF%A1JS-SDK%E6%8E%A5%E5%8F%A3#.E6.AD.A5.E9.AA.A4.E4.B8.80.EF.BC.9A.E5.BC.95.E5.85.A5JS.E6.96.87.E4.BB.B6 1.导入依赖包 npm install weixin-js-sdk 2.判断是否是在微信浏览器中 env.js <script> var ua = navig

  • 详解从vue的组件传值着手观察者模式

    观察者模式 首先,提到观察者模式,这不禁让我想到了MVVM,MVVM架构模式感觉用到了观察者的思想. 我们还是按照惯例,了解一下什么是观察者模式 观察者模式,类似发布订阅模式,完成这个动作首先最少得有两个不同的对象,或者多个对象,他更像是一种一队多的依赖关系,也就是一种对象的状态发生改变,与其相关所有的对象的状态都会发生改变:比如说朋友圈这个功能,一个人可能有上百个好友,当我发布一条朋友圈后,所有和我成为好友的人都会看见这个朋友圈,当另一个人点赞后,所有你的好友其他点赞的人也会收到通知,这很像观

  • 详解为什么Vue中的v-if和v-for不建议一起用

    本文主要介绍了为什么v-if和v-for不建议一起用?分享给大家,具体如下: 一.作用 v-if 指令用于条件性地渲染一块内容.这块内容只会在指令的表达式返回 true值的时候被渲染 v-for 指令基于一个数组来渲染一个列表.v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组或者对象,而 item 则是被迭代的数组元素的别名 在 v-for 的时候,建议设置key值,并且保证每个key值是独一无二的,这便于diff算法进行优化 两者在用法上 <

随机推荐