vue-router模式与vue-next-router新改变

更新视图但不重新请求页面”是前端路由原理的核心之一,目前在浏览器环境中这一功能的实现主要为前两种方式

  • hash: 使用 URL hash 值来作路由。默认模式。
  • history: 依赖 HTML5History API 和服务器配置
  • abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端

Vue2.0中的写法

const routes = [
  {
    name: 'home'
    path: '/',
    component: () => import('../components/view.vue')
  }
]

const router = new VueRouter({
  mode: 'hash',
  routes: routes
})

mode 参数用来控制路由模式,默认为hash模式,mode参数仅是一个标记,而实际起作用的是对象属性history的实现类,对应关系

  • 'history': HTML5History
  • 'hash': HashHistory
  • 'abstract': AbstractHistory

在初始化对应的history之前,会对mode做一些校验:若浏览器不支持HTML5History方式(通过supportsPushState变量判断),则mode强制设为'hash';若不是在浏览器环境下运行,则mode强制设为'abstract'

hash模式

http://www.example.com/index.html#home

hash ('#' 以及后面部分的内容)是不被包括在HTTP请求中的,因此改变 hash 不会重新加载页面,缺点就是只可修改 '#' 号之后的内容

HashHistory.push()

push()方法最主要的是对window的hash进行了直接赋值,window.location.hash = route.fullPath,hash的改变会自动将新路由添加到浏览器访问历史的栈顶,

从设置路由改变到视图更新的流程

$router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()

展开来说

1 $router.push() //调用方法

2 HashHistory.push() // 根据hash模式调用,设置hash并添加到浏览器历史记录(添加到栈顶)(window.location.hash= XXX)

3 History.transitionTo() // 监测更新

4 History.updateRoute() // 更新路由

5 {app._route= route} //替换当前app路由

6 vm.render() //更新视图

HashHistory.replace()

replace() 顾名思义是替换掉当前的路由,源码中调用window.location.replace方法将路由进行替换

history模式

History interface是浏览器历史记录栈提供的接口,通过back(), forward(), go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。

history.back();     // 等同于点击浏览器的回退按钮
history.go(-1);     //等同于history.back();

vue通过supportPushState()来检查浏览器是否支持history模式

从HTML5开始,History interface提供了两个新的方法:pushState() , replaceState() 使得我们可以对浏览器历史记录栈进行修改:

window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
  • stateObject:当浏览器跳转到新的状态时,将触发popState事件,该事件携带stateObject参数的副本

  • title:添加记录的标题

  • url:添加记录的url

这两个方法有个共同特点:当调用他们修改浏览器历史栈后,虽然当前url改变了,但浏览器不会立即发送请求该url,这就为单页应用前端路由,更新视图但不重新请求页面提供了基础

两种模式对比

history的优点:
  • pushState设置的新url可以是与当前url同源的任意url,而hash只可修改#后面的部分,故可设置与当前同文档的url
  • pushState设置的新url可以与当前url一模一样,这样也会把记录添加到栈中,而hash设置的新的值必须与原来不一样才会触发记录添加到栈中
  • pushState通过stateObject可以添加任意类型的数据记录中,而hash只可添加短字符串
  • pushState可额外设置title属性供后续使用
history的缺点:

对于单页面应用来说,理想的使用场景是仅仅在进入用用时加载index.html,后续在网络操作通过 ajax 完成,不会根据url重新请求页面,但是如果用户直接在地址栏中输入并回车,浏览器重启重新加载等特殊情况

Hash模式仅仅改变hash部分的内容,而hash部分是不会包含在http请求中的,就是#以及后面的是不会包含在请求当中的

如请求 http://baidu.com/#user/id ,只会发送http://baidu.com

所以hash模式下遇到根据url请求页面不会有问题

而history模式则将url修改的就和正式请求后端的url一样 http://baidu.com/user/id

如果这种向后端发送请求的话,后端没有配置对应/user/id的路由处理,会返回404错误,而id一般是一个动态的值

官方推荐的解决方法是在服务端增加一个覆盖所有情况的候选资源:如果url匹配不到任何静态资源,则应该返回同一个index.html页面,这个页面就是你app依赖的页面。同时这么做以后,服务器就不再返回404错误页面,因为对于所有路径都会返回index.html文件。为了避免这种情况,在vue应用里面覆盖所有的路由情况,然后再给出一个404页面。

如果是用node.js做后台,可以使用服务端的路由来匹配url,当没有匹配到路由的时候返回404,从而实现fallback

vue3.0中vue-next-router

router 的处理模式选择由原来的 mode: "history" 更改为 history: createWebHistory()。

// vue2-router
const router = new VueRouter({
  mode: 'history',
  ...
})

// vue-next-router
import { createRouter, createWebHistory } from 'vue-next-router'

const router = createRouter({
  history: createWebHistory(),
  ...
})

vue3中 push 或者 resolve 一个不存在的命名路由时,将会引发错误,这在vue2中会导航到根路由 "/" 并不渲染任何内容,控制台触发警告。

参考这篇源码理解
https://zhuanlan.zhihu.com/p/27588422

https://zhuanlan.zhihu.com/p/139045583

你可能感兴趣的:(vue-router模式与vue-next-router新改变)