關(guān)于秋招的一些感想
最近一段時間忙著秋招烈疚,一路經(jīng)歷了阿里終面掛,美團(tuán)終面掛等等聪轿,感覺自己有點苦逼(尤其是因為沒HC而掛是最難受的)爷肝。雖然到現(xiàn)在還沒得到滿意的結(jié)果,但這個過程還是有所收獲的陆错,這是雖然一個自我懷疑的過程灯抛,但也是一個不斷彌補自身不足,學(xué)習(xí)的過程音瓷,其中與一些面試我的師兄在交流的過程中也是受益匪淺对嚼,并且也對自身以后要走的路有了一個更加明確的認(rèn)識,所以前途漫漫還需努力呀外莲!
一猪半、路由
在現(xiàn)代前端開發(fā)中兔朦,路由是非常重要的一環(huán)偷线。但路由到底是什么呢?有些說:路由就是指隨著瀏覽器地址欄的變化沽甥,展示給用戶的頁面也不相同声邦。這是從路由的用途上來解釋路由是什么的,還有一種說法是:路由就是URL到函數(shù)的映射摆舟。這是從路由的實現(xiàn)原理上來解釋路由是什么的亥曹。這兩種說法都很有道理,但我個人認(rèn)為還是第二種比較切合我自己對路由的理解吧恨诱。
上面已經(jīng)說了上面是路由媳瞪,而路由本身也經(jīng)歷了不同的發(fā)展階段:
- 后端路由
- 前端路由
后端路由又可稱之為服務(wù)器端路由,因為對于服務(wù)器來說照宝,當(dāng)接收到客戶端發(fā)來的HTTP請求蛇受,就會根據(jù)所請求的相應(yīng)URL,來找到相應(yīng)的映射函數(shù)厕鹃,然后執(zhí)行該函數(shù)兢仰,并將函數(shù)的返回值發(fā)送給客戶端。對于最簡單的靜態(tài)資源服務(wù)器剂碴,可以認(rèn)為把将,所有URL的映射函數(shù)就是一個文件讀取操作。對于動態(tài)資源忆矛,映射函數(shù)可能是一個數(shù)據(jù)庫讀取操作察蹲,也可能是進(jìn)行一些數(shù)據(jù)的處理,等等。然后根據(jù)這些讀取的數(shù)據(jù)递览,在服務(wù)器端就使用相應(yīng)的模板來對頁面進(jìn)行渲染后叼屠,再返回渲染完畢的頁面。這種方式在早期的前端開發(fā)中非常普遍绞铃,它的好處與壞處都很明顯:
- 好處:安全性好镜雨,SEO好。
- 缺點:加大服務(wù)器的壓力儿捧,不利于用戶體驗荚坞,代碼冗合。
也正是由于后端路由還存在著自己的不足菲盾,前端路由才有了屬于自己的一片天地與發(fā)展的空間颓影。對于前端路由來說,路由的映射函數(shù)通常是進(jìn)行一些DOM的顯示和隱藏操作懒鉴。這樣诡挂,當(dāng)訪問不同的路徑的時候,會顯示不同的頁面組件临谱。前端路由主要有以下兩種實現(xiàn)方案:
- hash
- history API
當(dāng)然璃俗,前端路由也存在缺陷:使用瀏覽器的前進(jìn),后退鍵時會重新發(fā)送請求悉默,來獲取數(shù)據(jù)城豁,沒有合理地利用緩存。但總的來說抄课,現(xiàn)在前端路由已經(jīng)是實現(xiàn)路由的主要方式了唱星,我們常用的諸如react-router等前端框架的路由控制都是基于前端路由進(jìn)行開發(fā)的,因此將前端路由進(jìn)行一個了解
還是很有必要的跟磨。
二间聊、前端路由的實現(xiàn)
2.1 基于hash
早期的前端路由的實現(xiàn)就是基于location.hash來實現(xiàn)的。其實現(xiàn)原理也很簡單抵拘,location.hash的值就是URL中#后面的內(nèi)容哎榴。比如下面這個網(wǎng)站,它的location.hash='#me':
此外仑濒,hash也存在下面幾個特性:
- URL中hash值只是客戶端的一種狀態(tài)叹话,也就是說當(dāng)向服務(wù)器端發(fā)出請求時,hash部分不會被發(fā)送墩瞳。
- hash值的改變驼壶,都會在瀏覽器的訪問歷史中增加一個記錄。因此我們能通過瀏覽器的回退喉酌、前進(jìn)按鈕控制hash的切換热凹。
- 我們可以使用hashchange事件來監(jiān)聽hash的變化泵喘。
出發(fā)hsah變化的方式也有兩種,一種是通過a標(biāo)簽般妙,并設(shè)置href屬性纪铺,當(dāng)用戶點擊這個標(biāo)簽后,URL就會發(fā)生改變碟渺,也就會觸發(fā)hashchange事件了:
<a href="#srtian">srtian</a>
還有一種方式就是直接使用JavaScript來對loaction.hash進(jìn)行賦值鲜锚,從而改變URL,觸發(fā)hashchange事件:
location.hash="#srtian"
2.2 基于History API
前面的hash雖然也很不錯苫拍,但使用時都需要加上#芜繁,并不是很美觀。因此到了HTML5绒极,又提供了History API來實現(xiàn)URL的變化骏令。其中做最主要的API有以下兩個:history.pushState()和history.repalceState()。
這兩個API可以在不進(jìn)行刷新的情況下垄提,操作瀏覽器的歷史紀(jì)錄榔袋。唯一不同的是,前者是新增一個歷史記錄铡俐,后者是直接替換當(dāng)前的歷史記錄凰兑。此外,這兩個api都接受三個參數(shù):
window.history.pushState(null, null, "http://www.163.com");
- 狀態(tài)對象(state object):一個JavaScript對象高蜂,與用pushState()方法創(chuàng)建的新歷史記錄條目關(guān)聯(lián)聪黎。無論何時用戶導(dǎo)航到新創(chuàng)建的狀態(tài)罕容,會觸發(fā)popstate事件备恤,并能在事件中使用該對象。
- 標(biāo)題(title):一般瀏覽器會忽略锦秒,最好傳入null露泊。
- 地址(URL):就是需要新增的歷史記錄的地址,瀏覽器不會去直接加載改地址旅择,但后面也可能會去嘗試加載該地址惭笑。此外需要注意的是,傳入的URL與當(dāng)前URL應(yīng)該是同源的生真。
這一塊的詳情可以去看MDN沉噩,它做了一個比較詳細(xì)的介紹:
此外,還提供了popstate事件來監(jiān)聽歷史記錄的變化柱蟀。
可以看看下面這個實例:
<p id="example">
<a href="/name" title="name">name</a>
<a href="/age" title="age">age</a>?
</p>
<div class="main" id="main"></div>
<script>
;(function(){
var examplebox = document.getElementById('example')
var mainbox = document.getElementById('main')
examplebox.addEventListener('click', function(e){
e.preventDefault()
var elm = e.target
var uri = elm.href
var tlt = elm.title
history.pushState({path:uri,title:tlt}, null, uri)
mainbox.innerHTML = 'current page is '+tlt
})
window.addEventListener('popstate',function(e){
var state = e.state
mainbox.innerHTML = 'current page is ' + state.title
})
})()
</script>
兩種實現(xiàn)方式的對比:基于Hash的路由實現(xiàn)川蒙,兼容性更好;而基于History API的路由长已,則更正式畜眨,更美觀昼牛,可以設(shè)置與當(dāng)前URL同源的任意URL,路徑更直觀康聂。此外贰健,基于Hash的路由不需要對服務(wù)器做改動,基于History API的路由需要對服務(wù)器做一些改造恬汁,需要對不同的路由進(jìn)行相應(yīng)的設(shè)置才行伶椿。
三、React-Router
由于我現(xiàn)在也就對React-Router比較熟悉氓侧,Vue學(xué)了太久了悬垃,忘記了。Angular剛學(xué)甘苍,還沒到路由這塊這來尝蠕,因此就以React-Router為例,來聊聊現(xiàn)代前端框架的路由實現(xiàn)思路载庭。先來看看一個簡單的React中的Router代碼:
<Router>
<Switch>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
</Switch>
</Router>
其實現(xiàn)思路也很簡單如下圖所示:
其實現(xiàn)思路很簡單:About和User這兩個component一直都存在看彼。當(dāng)路由發(fā)生改變時,與URL相匹配的component機(jī)會被成功渲染囚聚。而不匹配的component就設(shè)置為null靖榕。
具體實現(xiàn),大家可以看這篇文章顽铸,這位大佬做了很詳細(xì)的介紹:
參考資料:
https://github.com/youngwind/blog/issues/109
https://zhuanlan.zhihu.com/p/24814675