IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue-router 解读更新视图但不重新请求页面 -> 正文阅读

[JavaScript知识库]vue-router 解读更新视图但不重新请求页面


前言

前两天,有一位小伙伴问我:

为什么说vue-router做到更新视图但不重新请求页面?我看路由更新都有请求数据啊。

针对这个问题,我从以下几点进行答复。


一、什么叫不重新请求页面

注意,这里说的是不重新请求页面,而不是说不会请求数据。请求数据是在你每个组件的生命周期中发起的。而重新请求页面,就相当于你直接点击了浏览器右上角的那个“重新加载此页”的按钮,而你在进行路由切换的时候,会发现浏览器的加载按钮并没有发生变化,所以是没有进行重新请求页面的。而至于它是如何做到不重新请求页面却更新了视图的呢。我们接着看。

二、vue-router的几种模式

如果有人问你,vue-router有几种模式?你可能会不假思索的回答说两种,那就是history和hash,因为这两个是常用到的。而vue-router还有第三种模式:abstract。接下来,我们一个一个来看一下这三种模式。

1、history

history模式在实现无刷新更新路由上主要用到了history提供的api:pushState,replaceState,以及 window 的 popstate 事件。看下mdn对这三个东东的介绍:
在这里插入图片描述

在这里插入图片描述
总的来说就是,通过pushState和replaceState来修改路由,页面不会重新加载。然后在浏览器导航发生变化的时候触发 popstate 事件。具体的实现代码可以看vue-router的源码,在src/history/html5.js 中

export class HTML5History extends History {
  // ...
  
  push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    // transitionTo 过渡函数
    this.transitionTo(location, route => {
    // 调用pushState函数,传入完整的url
      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其实和上面的pushState调用的是同一个函数
      replaceState(cleanPath(this.base + route.fullPath))
      handleScroll(this.router, route, fromRoute, false)
      onComplete && onComplete(route)
    }, onAbort)
  }

// 同步location的地址
  ensureURL (push?: boolean) {
    if (getLocation(this.base) !== this.current.fullPath) {
      const current = cleanPath(this.base + this.current.fullPath)
      push ? pushState(current) : replaceState(current)
    }
  }
	
	// 得到不带base的url,即域名后面的url
  getCurrentLocation (): string {
    return getLocation(this.base)
  }
}


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
  // 翻译一下上面那段英文,意思就是在safari上调用pushState超过100次会报“DOM Exception 18”的异常,所以这里加上了try catch
  const history = window.history
  try {
  // 如果replace为true,则调用history.replaceState否则调用 history.pushState
  // 在HTML5History 构造函数中,push直接调用的就是当前函数,replace则调用的是下面重新定义的一个函数replaceState 
    if (replace) {
      // preserve existing history state as it could be overriden by the user
      // 保留历史状态,这里没有重新生成key, getStateKey()获取的还是当前的key
      // 由于replace是直接替换掉路由堆栈中已存在的那个记录
      // 所以这里还是用之前的那个key就行
      const stateCopy = extend({}, history.state)
      stateCopy.key = getStateKey()
      history.replaceState(stateCopy, '', url)
    } else {
    // pushState是往路由堆栈中压入一个新的记录,所以这里的key要重新获取,通过genStateKey()重新生成一个key
      history.pushState({ key: setStateKey(genStateKey()) }, '', url)
    }
  } catch (e) {
  // 如果抛出异常,就进行重新赋值
    window.location[replace ? 'replace' : 'assign'](url)
  }
}
export function replaceState (url?: string) {
  pushState(url, true)
}

2、hash

这里要区分一下3.x版本之前的和之后的,两者的实现方式有所不同。

  • 2.x
    2.x版本的实现是通过hash实现的,也就是url中#后面那一段。hash虽然也在url中,但改变它却不会引起页面的重新加载。虽然不会引起页面的重载,但是浏览器也会记录它的每次改变。以下是源码的一角:
function pushHash (path) {
  window.location.hash = path
}

function replaceHash (path) {
  const href = window.location.href
  const i = href.indexOf('#')
  const base = i >= 0 ? href.slice(0, i) : href
  window.location.replace(`${base}#${path}`)
}
  • 3.x
    而到了3.x版本,vue-router进行了一次改版。其中主要的一点就是hash也采用了history的方式实现,当然,这里并不是完全抛弃了之前的hash,而是在支持histroy的情况下使用history的方式,否则还是用回之前的。来看下代码:
function pushHash (path) {
// supportsPushState判断是否支持history的实现方式,支持则用history,否则用hash
  if (supportsPushState) {
  // 这里的pushState和history模式里的pushState是同一个函数,都是定义在util/push-state.js文件下的。
    pushState(getUrl(path))
  } else {
    window.location.hash = path
  }
}

function replaceHash (path) {
  if (supportsPushState) {
    replaceState(getUrl(path))
  } else {
    window.location.replace(getUrl(path))
  }
}

3、abstract

abstract其实就是用一个数组stack来模拟路由栈,对路由的增加修改其实就是对这个数组的增加修改。具体的实现就不展开了。

结尾

关于那位小伙伴的疑问以及延伸出来的各个模式的实现原理,就扒拉到这里了。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:24:08  更:2022-10-17 12:24:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 15:58:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码