之前博客地址發生更改,重新發佈! 在傳統網站開發中,我們一般使用比如asp、php、jsp等技術進行開發,開發完成後統一部署在伺服器上,我們訪問時,會在瀏覽器中發送帶有'.asp','.php','.jsp'等尾碼路徑的url請求,伺服器會根據對應的路由映射表,找到我們請求的頁面並渲染成HTML,然 ...
之前博客地址發生更改,重新發佈!
在傳統網站開發中,我們一般使用比如asp、php、jsp等技術進行開發,開發完成後統一部署在伺服器上,我們訪問時,會在瀏覽器中發送帶有'.asp','.php','.jsp'等尾碼路徑的url請求,伺服器會根據對應的路由映射表,找到我們請求的頁面並渲染成HTML,然後把HTML頁面直接返回給瀏覽器展示,這就是所謂的伺服器端渲染SSR(Server Side Render)。
然而隨著前端頁面複雜性的提高以及前端技術的興起(尤其是Ajax技術的興起),行業內越來越推崇前後端分離的開發模式。使伺服器端不在關註HTML頁面的渲染,而是只專註於邏輯的開發,通過Api提供數據;前端只專註於UI的開發,把從伺服器請求的數據生成DOM插入到頁面中去。從伺服器請求數據,然後由客戶端通過前端技術生成展示頁面的方式就是客戶端渲染CSR(Client Side Render)。
客戶端渲染使前後端進行了分離,各自只關註屬於自己的部分,並且使用戶體驗也得到了提升,用戶交互不用每次都刷新頁面。基於這些優點,單頁應用(SPA(Single Page Web Application))的開發模型備受青睞。可以做到動態重寫當前頁面來與用戶交互,而不需要重新載入整個頁面。然而要實現單頁應用,做到交互和跳轉都不需要刷新的體驗,需要解決一個重要問題,就是路由問題。所以就有了前端路由,其實前端路由是相對於伺服器端路由的稱謂,由前端控制維護url和UI之間的映射關係,url更改後引起ui更新,而無需刷新頁面。
下麵就讓我們通過兩種方式實現前端路由:
實現前端路由的整體思路:
首先維護一張包含path和對應的頁面內容的路由映射表,當監聽到路由發生變化後,從路由映射表中篩選出對應的路由信息,並把路由信息中對應的內容頁面渲染添加到html頁面展示。開始之前先瞭解下兩種方式的基本知識。
1.window.history
Window.history是一個只讀屬性,用來獲取包含操作瀏覽器會話歷史History 對象。
主要方法:
back()
前往上一頁, 用戶可點擊瀏覽器左上角的返回按鈕模擬此方法. 等價於 history.go(-1)
forward()
在瀏覽器歷史記錄里前往下一頁,用戶可點擊瀏覽器左上角的前進按鈕模擬此方法. 等價於 history.go(1)
go()
通過當前頁面的相對位置從瀏覽器歷史記錄( 會話記錄 )載入頁面
pushState()
按指定的名稱和URL(如果提供該參數)將數據push進會話歷史棧,數據被DOM進行不透明處理;你可以指定任何可以被序列化的javascript對象。
replaceState()
按指定的數據,名稱和URL(如果提供該參數),更新曆史棧上最新的入口。這個數據被DOM 進行了不透明處理。你可以指定任何可以被序列化的javascript對象。
2.location.hash
hash 屬性是一個可讀可寫的字元串,該字元串是 URL 的錨部分(從 # 號開始的部分)。
實現代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>window.history路由</title>
</head>
<body>
<div>
<div id="routerLink">
<div>
<button onclick="historyChange('home')">首頁(history)/button>
<button onclick="historyChange('about')">關於(history)</button>
</div>
<div>
<button onclick="hashChange('home')">首頁(hash)</button>
<button onclick="hashChange('about')">關於(hash)</button>
</div>
</div>
<div>
<div id="routerView">
</div>
</div>
</div>
<!-- 2.創建子視圖模板 -->
<template id="home">
<div>hello,我是首頁</div>
</template>
<template id="about">
<div>hello,我是關於</div>
</template>
<script>
//1.首先創建路由表
const routerTable = [
{
path: 'home',
component: '#home'
},
{
path: 'about',
component: '#about'
}
]
//*********** 方式一:window.history **************
//3.(window.history)監聽路由更改,根據新路由path載入對應的內容
function historyChange(path) {
render({ path: path })
}
//添加popstate狀態監聽
window.addEventListener('popstate', function (e) {
if (e) {
render({ path: e.state, isPush: false })
}
})
//************** 方式二:location.hash ***************
function hashChange(path) {
render({ path: path, mode: 'hash' })
}
//添加hashchange監聽
window.addEventListener('hashchange', function () {
let path = location.hash
//path移除開始的#
render({ path: path.substring(1, path.length - 2), mode: 'hash' })
})
//**************公共方法*******************
//渲染方法
function render(data) {
//預設值,mode預設為history,isPush=true,isReplace=false,path=home
data = Object.assign({ mode: 'history', isPush: true, isReplace: false, path: 'home' }, data)
if (data.path) {
//查詢路由信息
const route = routerTable.find(p => p.path == data.path);
if (route) {
if (data.mode == 'history') {
if (data.isPush) {
//更改url---後退、前進不更改
if (data.isReplace) {
window.history.replaceState(data.path, '', data.path)
} else {
window.history.pushState(data.path, '', data.path)
}
}
} else if (data.mode == 'hash') {
location.hash = data.path
}
//更新html
document.querySelector("#routerView").innerHTML = document.querySelector(route.component).innerHTML
}
}
}
</script>
</body>
</html>
PS:需要用http的方式運行頁面,要不然pushState是無法使用的,會報:cannot be created in a document with origin 'null'的錯誤。
不過如果你電腦上已經安裝了vscode,可以下載Live Server插件,來運行html文件。