怎样理解Vue中的路由

1. 路由

  • 传统的路由指的是:当用户访问一个url时,对应的服务器会接收这个请求,然后解析url中的路径,从而执行对应的处理逻辑。这样就完成了一次路由分发。
  • 而前端路由是不涉及服务器的,是前端利用hash或者HTML5history API来实现的,一般用于不同内容的展示和切换。

目前Vue 推荐单页面应用 SPA 开发模式,大型单页应用最显著特点之一就是采用前端路由系统,通过改变URL,在不重新请求页面的情况下,更新页面视图。Vue中的路由解决方案为vue-router

它提供两种不同方式的路由方式:HashHistory,在 vue-router 中是使用了外观模式将几种不同的路由方式提供了一个一致的高层接口,让我们可以更解耦的在不同路由方式中切换。HashHistory 除了外观上的不同之外,还有一个区别是:Hash 方式的状态保存需要另行传递,而 HTML5 History 原生提供了自定义状态传递的能力,我们可以直接利用其来传递信息。

vue-router中是通过mode这一参数控制路由的实现模式的:

在这里插入图片描述

2. Hash

Hash 方法是在路由中带有一个 #,主要原理是通过监听 # 后的 URL 路径标识符的更改而触发的浏览器 hashchange 事件,然后通过获取 location.hash 得到当前的路径标识符,再进行一些路由跳转的操作,参见 MDN:

  • location.href:返回完整的 URL
  • location.hash:返回 URL 的锚部分;
  • location.pathname:返回 URL 路径名;
  • hashchange 事件:当 location.hash 发生改变时,将触发这个事件。

比如访问一个路径 http://sherlocked93.club/base/#/page1,那么上面几个值分别为:


# http://sherlocked93.club/base/#/page1
{
  "href": "http://sherlocked93.club/base/#/page1",
  "pathname": "/base/",
  "hash": "#/page1"
}

看一个例子:

<html>
<head>
  <style>
    li {
      cursor: pointer;
    }
  </style>
</head>
<body>
<div id="main">
  <p>router-hash</p>
  <ul id="list">
    <li><a href="#router1">router1</a></li>
    <li><a href="#router2">router2</a></li>
    <li><a href="#router3">router3</a></li>
  </ul>
  <div id="panel"></div>
</div>

<script>
  window.onload = function () {
    window.onhashchange = function (opt) {
      console.log('hash has changed to: ', location.hash)
    }
  }
</script>
</body>
</html>

效果:

在这里插入图片描述
当我们点击后退时,可见路由跳转回router2中。并且当我们刷新页面时不会报出404的错误,那是因为hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用。

3. History API

HTML5History API为浏览器的全局history对象增加的扩展方法。一般用来解决ajax请求无法通过回退按钮回到请求前状态的问题。

HTML4原有的和HTML5新提出的history的API有:

  • history.forward(); //在历史记录中前进一步
  • history.back(); //在历史记录中后退一步
  • history.go(n): //在历史记录中跳转n步骤,n=0为刷新本页,n=-1为后退一页。
  • history.pushState(data, title, url); //向历史记录中追加一条记录
  • history.replaceState(data, title, url); //替换当前页在历史记录中的信息
  • history.state; //是一个属性,可以得到当前页的state信息。
  • window.onpopstate; //是一个事件,在点击浏览器后退按钮或js调用forward()back()go()时触发。监听函数中可传入一个event对象,event.state即为通过pushState()replaceState()方法传入的data参数。

以一个例子实现一下:

<html>
<head>
  <style>
    li {
      cursor: pointer;
    }
  </style>
</head>
<body>
<div id="main">
  <p>vue-router</p>
  <ul id="list">
    <li>router1</li>
    <li>router2</li>
    <li>router3</li>
  </ul>
  <div id="panel"></div>
</div>

<script>
  window.onload = function () {
    window.onpopstate = function (event) {
      console.log(event)
    };

    document.querySelector('#list').addEventListener('click', function (event) {
      if(event.target.nodeName.toLowerCase()==="li") {
        var content = event.target.innerHTML;
        var _newState;
        _newState = {
          url: location.origin + '/' + content,
          title: document.title,
          state: content
        };

        window.history.pushState(_newState, '', '/' + content);
        console.log('you have change the router to: ', content);
      }
    })
  }
</script>
</body>
</html>

效果:

在这里插入图片描述
总而言之就是当浏览器访问一个页面时,当前地址的状态信息会被压入历史栈,当调用history.pushState()方法向历史栈中压入一个新的state后,历史栈顶部的指针是指向新的state的。可以将其作用简单理解为假装已经修改了url地址并进行了跳转 ,除非用户点击了浏览器的前进、回退,或是显式调用HTML4中的操作历史栈的方法,否则不会触发全局的popstate事件。以上例子中点击后退可见由当前的router2跳转到router3,控制台打印出popstate事件信息。

当我们刷新页面的时候,会报出404的错误:

在这里插入图片描述
这也是history不同于hash的一个地方,是因为history模式则会将URL修改得就和正常向后端发起请求一样,如果后端没有配置对应的路由处理,则会返回404错误。

官方推荐的解决办法是在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

参考:
https://www.cnblogs.com/dashnowords/p/9671213.html 大史不说话
https://juejin.im/post/5c52da9ee51d45221f242804 SHERlocked93

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值