写在结尾
左思右想还是决定再加一章,这章次要介绍路由的原理实现,并且会应用代码模仿VueRouter的原理。我学习前端的感觉是,框架有很多,会用就能够。但设计的思维却值得咱们去钻研,因为这才是框架的灵魂,以及真正的智慧所在。其实在应用框架的时候咱们不难发现,有些命令或者办法咱们用的多了甚至能猜出它的设计思维以及实现原理。所以纯熟应用一个框架或者并不难,但如果不能懂得它设计的初衷以及其中的奥秘,就总是会感觉短少一些什么。废话少说,进入正题。
1.模式
先看看这个:https://blog.csdn.net/fifteen...
援用其中的一段话,对于hash和history的区别(划重点,要考!):
hash模式url外面永远带着#号,咱们在开发当中默认应用这个模式。那么什么时候要用history模式呢?如果用户思考url的标准那么就须要应用history模式,因为history模式没有#号,是个失常的url适宜推广宣传。当然其性能也有区别,比方咱们在开发app的时候有分享页面,那么这个分享进来的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app外面url是不容许带有#号的,所以要将#号去除那么就要应用history模式,然而应用history模式还有一个问题就是,在拜访二级页面的时候,做刷新操作,会呈现404谬误,那么就须要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok啦。
VueRouter领有两种模式,那就是咱们相熟的hash和history,所以在设计时也要将这两种不同的模式都思考进来。代码如下:
hash:
<body> <!-- a标签 = router-link --> <a href="#/">首页</a> <a href="#/about">对于</a> <!-- div = router-view --> <div id="view"></div> <script> const vw = document.getElementById("view") window.addEventListener("hashchange", () => { if (location.hash == "#/") { vw.innerHTML = "我是首页" } else if (location.hash == "#/about") { vw.innerHTML = "我是对于" } }) </script></body>
看看成果:
那么问题来了,router-link的tag属性能够扭转显示的标签。也就是说如果不是默认的a标签该怎么做呢?持续改良,代码如下:
<body> <!-- 任意标签 = router-link --> <span style="color: deepskyblue;cursor:pointer;" onclick="changeHash('#/')">首页</span> <span style="color: deepskyblue;cursor:pointer;" onclick="changeHash('#/about')">对于</span> <!-- div = router-view --> <div id="view"></div> <script> function changeHash (path) { location.hash = path } window.addEventListener("hashchange", () => { if (location.hash == "#/") { view.innerHTML = "我是首页" } else if (location.hash == "#/about") { view.innerHTML = "我是对于" } }) </script></body>
看看成果:
解决方案就是咱们能够通过为任意标签增加点击事件,并在点击时传入对应的hash值,而后在点击事件处理函数中扭转地址栏的hash值。
能够看到,应用a标签和div模仿的vueRouter,仿佛还像那么回事儿。所以hash模式下路由的原理也不言而喻,说白了就是:
监听hashchange事件,而后依据地址栏上的门路,进行DOM渲染。
history:
<body> <!-- 任意标签 = router-link --> <span style="color: deepskyblue;cursor:pointer;" onclick="changeHash('/')">首页</span> <span style="color: deepskyblue;cursor:pointer;" onclick="changeHash('/about')">对于</span> <!-- div = router-view --> <div id="view"></div> <script> function changeHash (path) { history.pushState(null, null, path) if (location.pathname == "/") { view.innerHTML = "首页是我" } else if (location.pathname == "/about") { view.innerHTML = "对于是我" } } </script></body>
看看成果:
能够看到浏览器的回退和后退并没有成果,这也是与hash模式不同的中央。改良:
<body> <!-- 任意标签 = router-link --> <span style="color: deepskyblue;cursor:pointer;" onclick="changeHash('/')">首页</span> <span style="color: deepskyblue;cursor:pointer;" onclick="changeHash('/about')">对于</span> <!-- div = router-view --> <div id="view"></div> <script> function changeHash (path) { history.pushState(null, null, path) if (location.pathname == "/") { view.innerHTML = "首页是我" } else if (location.pathname == "/about") { view.innerHTML = "对于是我" } } window.addEventListener("popstate", () => { if (location.pathname == "/") { view.innerHTML = "首页是我" } else if (location.pathname == "/about") { view.innerHTML = "对于是我" } }) </script></body>
看看变动:
那么其实history模式下的路由原理其实也能够总结进去了:
应用history.pushState API来切换地址栏的门路,再通过监听popstate事件来操作浏览器的回退和后退按钮。
总结
代码没什么可讲的,着重说说hash和history各自的特点。
1.hash:"#" 能够了解为锚点,它的url会更改、浏览器能够后退和后退、但浏览器不会刷新、并且不会和服务端交换
2.history:无"#" 能够了解为没有锚点,它是标准的url、是可能拜访到后盾的、须要服务端的共事进行配合
原本想着这一章把原理的内容都写完,但切实是模仿路由的内容太多了,还是放在前面一点一点写完吧。本章曾经将路由的原理带进去了,前面的内容会绝对高级的实现路由。
Keep foolish, keep hungry.