抽丝剥茧看路由---2__原生JS仿写路由

…续前缘
上一篇文章只是作为本文的对比, 本文重点是原生JS仿写路由
既然是仿写, 那么结构自然要基本一样咯

index.html
<!DOCTYPE html >
<html >
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script type="text/javascript" src="js/main.js" ></script>
    <title>native route</title>
</head>
<body >
<!-- 路由标签 -->
<ul>
    <li><a href="#/test">test</a></li>
    <li><a href="#/dev">dev</a></li>
    <li><a href="#/others">others</a></li>
</ul>
<!-- 路由展示区 -->
<div id="route"></div>
</body>
</html>

其实在上周以前, 我根本不知道路由的原理, 直到上周某一天, 闲着无聊, 把上篇文章里面的元素挨个审查了一遍, 然后惊喜就来了…
审查到路由时的惊喜

或许你们会以为这没有什么, 但是当你发现metatitle标签, 如果再补上HTMLbody标签, 这不就是一个完整的页面吗?
很巧的是, 我知道ajax不仅可以用来做后台数据请求, 还能请求html或者jsp等页面静态化后的全部数据. 至于为什么会“丢失”htmlbody两个标签, 自己试试不就知道咯.
想到就做, 于是写了一些JS—window对象有一个hashchange事件, 每当页面地址的hash值变化时, 就会触发hashchange这个事件. 至于什么是hash值, 你可以把window.location这个对象打印出来, 实时监控它, 那你就知道啦

//route路由
window.addEventListener("hashchange", function(data){
  console.log(data);
  var route = window.location.hash.split("#")[1];
  switch(route){
    case "/test":
      var xhr = new XMLHttpRequest();
      xhr.open("get", "route/test.html", true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState==4 && xhr.status==200){
          document.getElementById("route").innerHTML = xhr.responseText;
        }
      }
      xhr.send(null);
      break;
    case "/dev":
      var xhr = new XMLHttpRequest();
      xhr.open("get", "route/dev.html", true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState==4 && xhr.status==200){
          document.getElementById("route").innerHTML = xhr.responseText;
        }
      }
      xhr.send(null);
      break;
    default:
      var xhr = new XMLHttpRequest();
      xhr.open("get", "route/default.html", true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState==4 && xhr.status==200){
          document.getElementById("route").innerHTML = xhr.responseText;
        }
      }
      xhr.send(null);
      break;
  }
});

紧接着就是route文件夹下面的三个html文件

default.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>default</title>
</head>
<body>
    <h1>defaultPage</h1>
</body>
</html>
dev.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dev</title>
</head>
<body>
    <h1>developmentEnviroment</h1>
</body>
</html>
test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <h1>testEnviroment</h1>
</body>
</html>

到此为止, 原生JS路由就写完了…但是, JS文件不觉得很是复杂吗, 所以我们把ajax函数提取出来精简

// ajax请求
  function xhrPage(url){
      var xhr = new XMLHttpRequest();
      xhr.open("get", url, true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState==4 && xhr.status==200){
          document.getElementById("route").innerHTML = xhr.responseText;
        }
      }
      xhr.send(null);
  }
  //route路由
window.addEventListener("hashchange", function(data){
  console.log(data);
  var route = window.location.hash.split("#")[1];
  switch(route){
    case "/test":
      xhrPage("route/test.html");
      break;
    case "/dev":
      xhrPage("route/dev.html");
      break;
    default:
      xhrPage("route/default.html");
      break;
  }
});

这样看着是不是很清爽? 而这也符合函数式编程的思想(还有一个是面向对象编程:OOP无非是把函数写到对象的一个属性中)—能避免大量代码冗余以及使结构清晰, 也利于复用. 现在如果再点击路由标签, 会发现下面能显示相应的页面
路由示意图
而不出所料, 原生加载的文档与ng框架加载出来的页面是一样的. 也就是说—至少这个思想没问题, 只是实现方法不同而已
DOM文档

测试之后, 或许你又会发现一个问题, 在ng中, 页面一进来就会呈现路由加载后的情形, 而自己写的只有在点击后才会出现路由, 所以再进行改进(猜测: 可能是ng中用了window.location.href这个属性)

  // ajax请求
  function xhrPage(url){
      var xhr = new XMLHttpRequest();
      xhr.open("get", url, true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState==4 && xhr.status==200){
          document.getElementById("route").innerHTML = xhr.responseText;
        }
      }
      xhr.send(null);
  }

  function hashChange(route){
    switch(route){
      case "/test":
        xhrPage("route/test.html");
        break;
      case "/dev":
        xhrPage("route/dev.html");
        break;
      default:
        xhrPage("route/default.html");
        break;
    }
  }
  //route路由
  window.addEventListener("hashchange", function(data){
    console.log(data);
    var route = window.location.hash.split("#")[1];
    hashChange(route);
  });

  window.addEventListener("load", function(){
    var _route = window.location.href.split("#")[1];
    hashChange(_route);
  });

这样改进代码之后的确实现了进来就加载路由
这里写图片描述
好了, 再回过来解释问题: 没有html和body
因为浏览器有自动补全(删除)机制, htmlbody在一个document里面只能加载一次, 其余的都会被浏览器智能删掉. 可以通过DevTools的sources面板来查看.
想必vue的路由加载机制与此出入不大…
如果文中有什么不对的地方, 敬请指正.
打完, 收工.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值