前端入门之(vue-router全解析一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vv_bug/article/details/82795248

前言: 一直想着啥时候能把vue全家桶的东西源码全部撸一遍,可惜无奈能力有限啊(哈哈,最近一直在补js基础),看vuex代码的时候觉得也还好,基本上是边学边解析源码的方式把vuex撸了一遍(毕竟整个vuex加起来也没多少代码),可当碰到vue-router的时候,首先就被它那几千行代码吓到了,刚开始看的时候是有点懵逼啊,所以把vue-router官网上的api看了一遍又一遍, 然后带着某个api功能再去看的源码,然后一行一行的debug,哈哈! 我能说我把vue-router的源码都debug了个遍吗?? 嗯嗯~~ 不推荐小伙伴这样干哈,太浪费时间,纠结了好久,文章也是真的不知道该怎么写,下面记录下我学习vue-router的笔记,大牛勿喷!

先附上vue-router的官网:
https://router.vuejs.org/zh/
在学习vue-router之前,我们先认识两个东西:

window.history.pushState()、window.history.replaceState()
window.location.hash
我们一个一个来哈,先说一下history对象的pushState跟replaceState方法
pushState方法: 简单的来说就是向浏览器插入一条历史记录
replaceState方法: 替换浏览器中的一条历史记录

我这只是简单的描述了一下哈,童鞋们如果需要深入了解的话,可以去看这上面的解释,比我专业的多哈https://developer.mozilla.org/zh-CN/docs/Web/API/History_API

pushState跟replaceState方法可以在不重新加载页面的情况下修改location跟浏览器的历史记录,这样说有点抽象哈,我们结合我们的demo来说一下.

需求是这样的: 我们需要通过location的变化,去匹配我们当前的页面,达到路由跳转的效果,具体实现的效果看截图.

在这里插入图片描述

可以看到,当我们点击按钮“跳转b页面”的时候,我们的container模块切换到了b页面.然后点击按钮“返回a页面”的时候,切换到了a页面.

好啦,我们一步一步的来实现!

首先创建两条标签数据来模拟a跟b页面:

var components = {
    a: '<div style="height: 500px;text-align: center;color: #000;font-size: 20px;background-color: red">我是a页面</div>',
    b: '<div style="height: 500px;text-align: center;color: #000;font-size: 20px;background-color: yellow">我是b页面</div>'
  };

然后初始化一个页面:

//初始化一个a页面
  push('a');
  /**
   * 添加一个页面
   * @param pageName  页面名称
   */
  function push(pageName) {
    // 增加一个历史记录
    history.pushState(pageName, '', pageName+'.html');
    //更新当前页面
    updateCom(components[pageName]);
  }
   /**
   * 更新当前container
   * @param com
   */
  function updateCom(com) {
    var container = document.getElementById('container');
    container.innerHTML = com;
    console.log(container);
  }

当我们点击按钮跳转b页面的时候,我们调用push方法替换当前页面,并且通过pushstate方法添加一条历史记录:

<button onclick="push('b')">点我跳转到b页面</button>

此时我们可以看到,我们的url变成了

http://localhost:xx/VuexDemo/b.html

页面也切换到了b页面

最后当我们点击返回a页面按钮的时候,我们直接调用:

 /**
   * 浏览器返回
   */
  function back() {
    history.go(-1);
  }

然后监听state的变化,并且根据当前state处理页面跳转:

 //监听浏览器的返回操作
  window.addEventListener('popstate', function () {
    var state = history.state;
    updateCom(components[state]);
  });

最后运行代码就可以看到我们截图的效果了,代码比较简单,我就直接全部附上了:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style type="text/css">
    button {
      font-size: 40px;
    }
  </style>
</head>
<body style="text-align: center;">
<button onclick="push('b')">点我跳转到b页面</button>
<br>
<button onclick="back()">点我返回a页面</button>
<br>
<div id="container"></div>
<script>
  var components = {
    a: '<div style="height: 500px;text-align: center;color: #000;font-size: 20px;background-color: red">我是a页面</div>',
    b: '<div style="height: 500px;text-align: center;color: #000;font-size: 20px;background-color: yellow">我是b页面</div>'
  };
  //监听浏览器的返回操作
  window.addEventListener('popstate', function () {
    var state = history.state;
    updateCom(components[state]);
  });
  //初始化一个a页面
  push('a');

  /**
   * 添加一个页面
   * @param pageName  页面名称
   */
  function push(pageName) {
    // 增加一个历史记录
    history.pushState(pageName, '', pageName+'.html');
    //更新当前页面
    updateCom(components[pageName]);
  }

  /**
   * 浏览器返回
   */
  function back() {
    history.go(-1);
  }

  /**
   * 更新当前container
   * @param com
   */
  function updateCom(com) {
    var container = document.getElementById('container');
    container.innerHTML = com;
    console.log(container);
  }
</script>
</body>
</html>

貌似不是所有的浏览器都支持pushstate跟replacestate方法,所以还有一种实现这种效果的方法,那就是我们接下来要说的location.hash了.
#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包括#,并且每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置,最后还可以通过onhashchange事件监听hash的变化,我们直接模拟一下上面的demo哈.

代码比较简单,跟上面pushstate的方式大致一样,我就直接贴代码了哈:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style type="text/css">
    button {
      font-size: 40px;
    }
  </style>
</head>
<body style="text-align: center;">
<button onclick="push('b')">点我跳转到b页面</button>
<br>
<button onclick="back()">点我返回a页面</button>
<br>
<div id="container"></div>
<script>
  var components = {
    a: '<div style="height: 500px;text-align: center;color: #000;font-size: 20px;background-color: red">我是a页面</div>',
    b: '<div style="height: 500px;text-align: center;color: #000;font-size: 20px;background-color: yellow">我是b页面</div>'
  };
  window.addEventListener('hashchange', function () {
    //获取当前location的hash值
    var hash = window.location.hash;
    //根据当前hash值做路由跳转
    updateCom(components[hash.substring(hash.indexOf('#')+1)]);
  });
  //初始化一个页面a
  push('a');

  /**
   * 添加一个页面
   * @param pageName
   */
  function push(pageName) {
    // 修改当前location的hash值,并且增加一个历史记录
    location.hash=pageName;
    //更新当前路由
    updateCom(components[pageName]);
  }

  function back() {
    history.go(-1);
  }

  function updateCom(com) {
    var container = document.getElementById('container');
    container.innerHTML = com;
  }
</script>
</body>
</html>

最后运行的效果跟上面的demo一样.

那除了兼容性问题,我们为啥不直接用location的hash的方式呢? 为啥还用pushstate的方式呢?

在某种意义上,调用 pushState() 与 设置 location.hash的方式 类似,二者都会在当前页面创建并激活新的历史记录。但 pushState() 具有如下几条优点:

新的 URL 可以是与当前URL同源的任意URL 。而设置 window.location 仅当你只修改了哈希值时才保持同一个 document。
如果需要,你可以不必改变URL。而设置 window.location = “#foo”;在当前哈希不是 #foo 的情况下, 仅仅是新建了一个新的历史记录项。
你可以为新的历史记录项关联任意数据。而基于哈希值的方式,则必须将所有相关数据编码到一个短字符串里。
假如 标题 在之后会被浏览器用到,那么这个数据是可以被使用的(哈希则不然)。
好啦!!! 有小伙伴要说了,你不是在写vue-router的文章吗? 对的!! 不知道小伙伴有没有感觉了呢?? 其实整个vue-router最主要的就是利用了pushstate跟location.hash来实现的,只是针对vue跟api做了一系列的封装.这也许就是一个干了20年的程序员写helloworld跟一个刚起步程序员的区别了,哈哈!! 不早啦,睡啦睡啦~~~ 未完待续哈!

欢迎入群,欢迎交流,qq群链接:
在这里插入图片描述

参考链接:

猜你喜欢

转载自blog.csdn.net/vv_bug/article/details/82795248