抽丝剥茧看路由---2__原生JS仿写路由
…续前缘
上一篇文章只是作为本文的对比, 本文重点是原生JS仿写路由
既然是仿写, 那么结构自然要基本一样咯
index.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 routetitle>
head>
<body >
<ul><li><a href="#/test">testa>li><li><a href="#/dev">deva>li><li><a href="#/others">othersa>li>
ul>
<div id="route">div>
body>
html>
其实在上周以前, 我根本不知道路由的原理, 直到上周某一天, 闲着无聊, 把上篇文章里面的元素挨个审查了一遍, 然后惊喜就来了…
或许你们会以为这没有什么, 但是当你发现meta
和title
标签, 如果再补上HTML
和body
标签, 这不就是一个完整的页面吗?
很巧的是, 我知道ajax不仅可以用来做后台数据请求, 还能请求html
或者jsp
等页面静态化后的全部数据. 至于为什么会“丢失”掉html
和body
两个标签, 自己试试不就知道咯.
想到就做, 于是写了一些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
<html lang="en">
<head><meta charset="UTF-8"><title>defaulttitle>
head>
<body><h1>defaultPageh1>
body>
html>
dev.html
<html lang="en">
<head><meta charset="UTF-8"><title>devtitle>
head>
<body><h1>developmentEnviromenth1>
body>
html>
test.html
<html lang="en">
<head><meta charset="UTF-8"><title>testtitle>
head>
<body><h1>testEnviromenth1>
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框架加载出来的页面是一样的. 也就是说—至少这个思想没问题, 只是实现方法不同而已
测试之后, 或许你又会发现一个问题, 在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
因为浏览器有自动补全(删除)机制, html
和body
在一个document里面只能加载一次, 其余的都会被浏览器智能删掉. 可以通过DevTools的sources面板来查看.
想必vue的路由加载机制与此出入不大…
如果文中有什么不对的地方, 敬请指正.
打完, 收工.
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!