1. 認(rèn)識前端路由和后端路由
前端路由相對于后端路由而言的, 在理解前端路由之前先對于路由有一個基本的了解
路由: 簡而言之,就是把信息從原地址傳輸?shù)侥康牡氐幕顒?/p>
對于我們來說路由就是: 根據(jù)不同的url地址展示不同的頁面內(nèi)容
1.1 后端路由
以前咱們接觸比較多的后端路由,當(dāng)改變url地址時,瀏覽器會向服務(wù)器發(fā)送請求,服務(wù)器根據(jù)這個url,返回不同的資源內(nèi)容
后端路由的特點就是
- 前端每次跳轉(zhuǎn)到不同url地址,都會重新訪問服務(wù)器,
- 服務(wù)器根據(jù)前端的路由,返回不同的數(shù)據(jù),或者是HTML頁面
1.2 前端路由
前端路由是指通過一定的技術(shù)手段,在跳轉(zhuǎn)路由時不在向服務(wù)器發(fā)送請求, 而在在瀏覽器端進(jìn)行處理,
通過不同的url映射到頁面不同的DOM元素,不同的url顯示不同的頁面內(nèi)容
也就是說
后端路由是url地址映射到服務(wù)器上的某些資源
前端路由是url地址映射到瀏覽器上的某些資源
1.3 什么時候使用到前端路由?
在我們開發(fā)單頁面應(yīng)用的時候,會常使用到前端路由
那么什么是單頁面應(yīng)用?
單頁面應(yīng)用的說明
- 以前后端路由不同的url地址會返回不同的HTML頁面,也就是說整個項目不止一個HTML頁面
- 單頁面是指整個項目只有一個頁面, 頁面顯示的內(nèi)容被抽離為一個一個小的組件
- 通過前端路由,讓url地址的改變來映射到不同的組件, 通過url的改變來決定組件的顯示與否
1.4 單頁面開發(fā)的優(yōu)缺點
優(yōu)點: 用戶體驗好
說明
- 單頁面只有一個頁面,在第一次加載時,就已經(jīng)將所有資源從服務(wù)下載
- 在通過前端路由切換頁面時,不是像服務(wù)器發(fā)送的請求,我們只是通過url決定哪些資源顯示
- 因為不用向服務(wù)器發(fā)送請求,所以請求/響應(yīng)造成的等待時間就會大大減少,提高了響應(yīng)速度.
缺點:
不利于SEO優(yōu)化(單頁面應(yīng)用,只有一個頁面會被百度收錄,其他的頁面都是虛擬的)
使用瀏覽器的前進(jìn)后退鍵的時候會重新發(fā)請求,沒有合理的利用緩存
單頁面無法記住之前滾動條的位置,無法在前進(jìn),后退的時候記住滾動的位置
2. 認(rèn)識前端渲染和后端渲染
在理解前端渲染和后端渲染之前,先理解什么是渲染,渲染什么.
渲染就是將數(shù)據(jù)和HTML模板組合成為一個完整的能讓瀏覽器顯示說有信息內(nèi)容的頁面
2.1 后端渲染
后端渲染也常被稱作為服務(wù)端的渲染
服務(wù)的渲染的說明:
- 當(dāng)用戶發(fā)送一個url請求是,服務(wù)器會根據(jù)路由獲取對應(yīng)的模板和數(shù)據(jù),
- 然后服務(wù)器會將數(shù)據(jù)和模板組合成為一個完整的html頁面發(fā)送給前端
- 瀏覽器獲取的是一個完整的HTML頁面,這就是服務(wù)的渲染
服務(wù)端渲染的好處:
- 前端資源消耗少, 所有的數(shù)據(jù)和模板組合是在后端完成的,因此不占用客戶端的運算資源(模板解析)
- 首屏加載時間快,因為瀏覽器獲取的就是一個完整的頁面,因此獲取后瀏覽器直接可以渲染視圖
- SEO優(yōu)化好, 因為SEO蜘蛛在獲取頁面內(nèi)容的時候是一個完整的頁面內(nèi)容,可以更好的分析頁面內(nèi)容
服務(wù)端渲染的壞處:
- 占用太多服務(wù)器 資源
2.2 前端渲染
前端渲染也常被稱為客戶端渲染
前端渲染說明:
- 前端渲染是指瀏覽器將頁面模板和數(shù)據(jù)進(jìn)行組合形成最終的HTML頁面
- 原理就是瀏覽器通過url獲取服務(wù)器頁面模板,服務(wù)器并不需要消化太多資源,直接將頁面模板發(fā)送給前端
- 瀏覽器拿到頁面也后,在解析頁面是,通過頁面中的ajax向后端請求數(shù)據(jù)
- 服務(wù)器根據(jù)前端對于數(shù)據(jù)的請求,返回給前端數(shù)據(jù)
- 瀏覽器拿到數(shù)據(jù)以后在和頁面模板整合,形成最終的頁面.
前端渲染的好處:
- 網(wǎng)絡(luò)傳輸數(shù)據(jù)量小,因為一個完整的頁面是通過兩次請求獲取的
- 模板在前端,因此可以通過請求不同的數(shù)據(jù)改變頁面顯示結(jié)果,
- 進(jìn)而減少后端渲染時,每次請求都會返回模板解析后的結(jié)果
- 不占用服務(wù)器資源
前端渲染的壞處:
- 前端資源消耗較多,因為模板的解析和數(shù)據(jù)的處理都是需要前端處理
- 對于SEO優(yōu)化不是特別的友好, 因為搜索引擎蜘蛛獲取的是頁面模板,沒法分析頁面全部內(nèi)容
3. 前端路由實現(xiàn)的技術(shù)
現(xiàn)在對于前端路由的原理有了一定的了解,那么通過什么技術(shù)才能達(dá)到,在改變url地址是,瀏覽器不會向服務(wù)發(fā)送請求呢?
3.1 基于hash實現(xiàn)的前端路由
其實在學(xué)習(xí)HTML,CSS階段,就已經(jīng)接觸并使用hash來處理頁面錨點鏈接.
因此通過hash的改變,url不會向服務(wù)器發(fā)送請求,這就是用來前端路由的一種技術(shù)手段
hash的說明:
- hash就是完整的url地址#后面的內(nèi)容
- Web 服務(wù)不會解析 hash,因為hash 僅僅是客戶端的一個狀態(tài)
- 反而前端就可以在
JavaScript中通過window.location.hash來讀取到 - 前端在讀取到hash以后,就可以通過hash所代表的不同路徑處理頁面不同的顯示邏輯
hash的特點
- hash 能兼容低版本的瀏覽器
- hash值的改變,不會向服務(wù)器發(fā)送請求,hash改變的值,只會在瀏覽器的訪問歷史中增加記錄
- 因此可以通過瀏覽器的前進(jìn),后推按鈕切換hash
hash演示示例:
因為每一次hash值發(fā)生變化都會觸發(fā)window.onhashchange事件,因此可以利用hash處理前端路由
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
padding: 0;
margin:0;
}
li{
list-style:none;
}
ul{
display: flex;
position: fixed;
bottom: 0;
left: 0;
right:0;
height:60px;
border-top:1px solid #999;
}
li{
flex:1;
background: #eee;
border-right:1px solid #999;
}
a{
display:block;
line-height:60px;
text-align: center;
font-size:20px;
text-decoration: none;
}
.content{
position: fixed;
top:0;
left:0;
right:0;
bottom:61px;
background: skyblue;
color:#fff;
text-align:center;
font-size:40px;
line-height: 80px;
}
.box{
display:none;
}
.show{
display:block;
}
</style>
</head>
<body>
<ul>
<li>
<a href="#/">首頁</a>
</li>
<li>
<a href="#/list">列表</a>
</li>
<li>
<a href="#/about">關(guān)于作者</a>
</li>
</ul>
<div class="content">
<div id="home" class="show">首頁</div>
<div id="list" class="box">列表頁</div>
<div id="about" class="box">關(guān)于作者</div>
</div>
<script>
window.onhashchange = function(){
let path = window.location.hash.slice(1)
// console.log(path );
switch(path){
case "/":
home.className = "show";
list.className = "box"
about.className = "box"
break;
case "/list":
home.className = "box";
list.className = "show"
about.className = "box"
break;
case "/about":
home.className = "box";
list.className = "box"
about.className = "show"
break;
}
}
</script>
</body>
</html>
示例過于簡單,請不要在意,重點關(guān)注,利用hash,咱們實現(xiàn)了路由的跳轉(zhuǎn),但是頁面沒有任何刷新.
這就是前端路由的精髓

3.2 基于HTML新增的history API實現(xiàn)前端路由
HTML新增了history API,來操作路瀏覽器的歷史,因為瀏覽器窗口會提供一個history對象,用來保存用戶操作的歷史,
history說明:
- 因為瀏覽器窗口提供了history來保存歷史操作的url,
- 因此使用前進(jìn)后退按鍵時,url地址會發(fā)生變化,但不會向服務(wù)器發(fā)送請求
- 但是history里保存的歷史記錄都是你訪問過的路由,
- 那么我們只需要通過一定的API,將一些url路由添加到history歷史記錄中就可以實現(xiàn)不發(fā)送請求的路由跳轉(zhuǎn)
- 因此需要借助于操作history的API
history API
- history.pushState: 向history對象中添加一條歷史記錄
- history.replaceState: 替換掉當(dāng)前的history記錄
- 兩個方法都接受三個參數(shù), 分別為state, title, url
pushState和replaceState 參數(shù)
- state用來存放將要插入的history實體的相關(guān)信息,它是一個json格式的參數(shù);
- title就是傳入history實體的標(biāo)題
- url用來傳遞新的history實體的相對路徑
history提供的這兩個方法不會主動觸發(fā)瀏覽器頁面的刷新,只是history對象包括地址欄的內(nèi)容會發(fā)生改變,當(dāng)出發(fā)前進(jìn)后退等history事件時才會進(jìn)行相應(yīng)的響應(yīng)。
history 實現(xiàn)前端路由示例:
代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
padding: 0;
margin:0;
}
li{
list-style:none;
}
ul{
display: flex;
position: fixed;
bottom: 0;
left: 0;
right:0;
height:60px;
border-top:1px solid #999;
}
li{
flex:1;
background: #eee;
border-right:1px solid #999;
}
a{
display:block;
line-height:60px;
text-align: center;
font-size:20px;
text-decoration: none;
}
.content{
position: fixed;
top:0;
left:0;
right:0;
bottom:61px;
background: skyblue;
color:#fff;
text-align:center;
font-size:40px;
line-height: 80px;
}
.box{
display:none;
}
.show{
display:block;
}
</style>
</head>
<body>
<ul>
<li>
<a id="homelink">首頁</a>
</li>
<li>
<a id="listlink">列表</a>
</li>
<li>
<a id="aboutlink">關(guān)于作者</a>
</li>
</ul>
<div class="content">
<div id="home" class="show">首頁</div>
<div id="list" class="box">列表頁</div>
<div id="about" class="box">關(guān)于作者</div>
</div>
<script>
homelink.onclick = function(){
history.replaceState({},"home","/home")
home.className = "show";
list.className = "box"
about.className = "box"
}
listlink.onclick = function(){
history.replaceState({},"list","/list")
home.className = "box";
list.className = "show"
about.className = "box"
}
aboutlink.onclick = function(){
history.replaceState({},"about","/about")
home.className = "box";
list.className = "box"
about.className = "show"
}
</script>
</body>
</html>
示例圖:

同樣的,我們會發(fā)現(xiàn)頁面的路徑雖然發(fā)生改變,但是瀏覽器并未向服務(wù)器發(fā)送請求,也沒有刷新頁面.
當(dāng)然了,這里提及前端路由,是想讓大家理解前端路由的概念和實現(xiàn)的技術(shù).
Vue的路由也是基于這些技術(shù)實現(xiàn)的, 當(dāng)然了Vue路由一定是經(jīng)過封裝處理的,
之后我們就要看看研究研究Vue的路由了