1、路由是什么?
2、hash模式、history模式、memory模式
1、路由是什么?
家里上網(wǎng)
- 貓:調(diào)制解調(diào)器,虛擬信號變成數(shù)字信號/數(shù)字信號變成虛擬信號。
調(diào)制器 制器是指通過數(shù)字信號處理技術(shù)
解調(diào)器 調(diào)制產(chǎn)生的振蕩或波中恢復(fù)原調(diào)制信號的器件 - 如果有多人上網(wǎng)就需要路由器
people-----路由器------電信(出售網(wǎng)絡(luò)IP/端口)------百度、騰訊、抖音購買幾千個IP作為他的服務(wù)器。
上網(wǎng)的時候 你連路由器 路由器看你想連哪里 。
比如想去抖音,路由器把你信號發(fā)給了抖音 ,然后抖音就過來了(電信那邊太復(fù)雜略過)。
分發(fā)
只要滿足一對多 就叫做分發(fā) 就是分別發(fā)送到各個地方
路由器主要是用來分發(fā)請求的,只要一個東西分發(fā)了請求 那這就是路由
這個東西就叫做路由器
路由就是分發(fā)請求的東西, 這是上網(wǎng)路由
我們要搞前端路由,
路由(維基百科):
通過互聯(lián)的網(wǎng)絡(luò)把信息從源地址傳輸?shù)侥康牡氐刂返幕顒印?br>
路由發(fā)生在OSI網(wǎng)絡(luò)參考模型中的第三層:網(wǎng)絡(luò)層。
路由引導(dǎo)分組轉(zhuǎn)送,經(jīng)過一些中間節(jié)點(diǎn)后,到達(dá)他們最后的目的地。做成硬件的話稱之為路由器。
路由器通常根據(jù)路由表(一個存儲到各個目的地最佳路徑的表)來引導(dǎo)分組轉(zhuǎn)送。
路由器(維基百科):是一種電訊網(wǎng)絡(luò)設(shè)備,提供路由與轉(zhuǎn)送兩種重要機(jī)制。
前端路由:
我們寫一個
用戶---路由--四個界面(div)
通過路由判斷用戶想進(jìn)哪個頁面
我們通過URL來進(jìn)入不同div
http:/127.00.1/#1 DIV1
http:/127.00.1/#2 DIV2
http:/127.00.1/#3 DIV3
http:/127.00.1/#4 DIV4
根據(jù)用戶的URL是#X 展示不同的divX
簡單的路由實現(xiàn)
注:
- hash就是URL #后面的東西包括#
- 由于JS執(zhí)行完一遍就結(jié)束了,只能更改一次,所以要監(jiān)聽這個事件
- 當(dāng)URL的片段標(biāo)識符更改時(#x)將觸發(fā)hashchange事件
- 默認(rèn)路由、保底路由、嵌套路由
JS
//默認(rèn)路由
number = number || 1
//第一遍用于默認(rèn)頁面
let number = window.location.hash.substr(1)
//獲取界面
let div = document.querySelector(`#div${number}`)
let app = document.querySelector("#app")
//渲染界面+404路由
if (div){
div.style.display = 'block';
}else{
div = document.querySelector("#div404")
div.style.display = 'block';
}
//展示出來
app.appendChild(div)
window.addEventListener('hashchange',()=>{
console.log("hash 變了")
let number2 = window.location.hash.substr(1)
let div2 = document.querySelector(`#div${number2}`)
let app2 = document.querySelector("#app")
if (div2){
div2.style.display = 'block';
}else{
div2 = document.querySelector("#div404")
div2.style.display = 'block';
}
//把之前的div拿出來并隱藏
app2.children[0].style.display = 'none'
document.body.appendChild(app2.children[0])
app2.appendChild(div2)
})
HTML
<a href="#1">go to 1</a>
<a href="#2">go to 2</a>
<a href="#3">go to 3</a>
<a href="#4">go to 4</a>
<div id="app"></div>
<div id = "div1" style="display: none">1</div>
<div id = "div2" style="display: none">2</div>
<div id = "div3" style="display: none"> 3</div>
<div id = "div4" style="display: none">4</div>
<div id = "div404" style="display: none">404</div>
JS代碼優(yōu)化
function route(){
//第一遍用于默認(rèn)頁面
let number = window.location.hash.substr(1)
let app = document.querySelector("#app")
number = number || 1
let div = document.querySelector(`#div${number}`)
if (!div){
div = document.querySelector("#div404")
}
div.style.display = 'block';
if (app.children.length>0){
//如果有就踢出去
app.children[0].style.display = 'none'
document.body.appendChild(app.children[0])
}
app.appendChild(div)
}
route()
window.addEventListener('hashchange',()=>{
console.log("hash 變了")
route()
})
路由表
自定義hasn和div的對應(yīng)關(guān)系
路由表 保存著去往每個網(wǎng)址的東西 表驅(qū)動編程
JS
const div1 = document.createElement('div')
div1.innerHTML = '1'
const div2 = document.createElement('div')
div2.innerHTML = '2'
const div3 = document.createElement('div')
div3.innerHTML = '3'
const div4 = document.createElement('div')
div4.innerHTML = '4'
const routeTable = {
'1':div1,
'2':div2,
'3':div3,
'4':div4,
}
function route(){
let number = window.location.hash.substr(1)
let app = document.querySelector("#app")
number = number || 1
let div = routeTable[number.toString()]
if (!div){
div = document.querySelector("#div404")
}
div.style.display = 'block';
app.innerHTML = ''
app.appendChild(div)
}
route()
window.addEventListener('hashchange',()=>{
console.log("hash 變了")
route()
})
HTML
<a href="#1">go to 1</a>
<a href="#2">go to 2</a>
<a href="#3">go to 3</a>
<a href="#4">go to 4</a>
<div id="app"></div>
<div id = "div404" style="display: none">
404
</div>
嵌套思路:頁面中還有頁面
路由的三種模式
hash模式 history模式 memory模式?
上面的路由是通過hash做的 #x 進(jìn)入x頁面
我不要#1 我直接/1 行不行
hash模式
使用規(guī)則:任何情況都可以用hash做前端路由
缺點(diǎn):SEO不友好
window.location.hash
hash示例
注:
- 瀏覽器是不會把#之后的內(nèi)容發(fā)給服務(wù)器
- 服務(wù)器收不到hash,導(dǎo)致訪問baidu.com/#1 baidu.com/#2 服務(wù)器認(rèn)為這些頁面會被認(rèn)為直接訪問baidu.com 。
- 這三個頁面內(nèi)容不一樣但是只有一個URL
- 沒有辦法收錄你的內(nèi)容 就叫做SEO不友好
那瀏覽器怎么展示你的三個頁面呢 他會永遠(yuǎn)只展示默認(rèn)路由 baidu.com 因為別的會被吃掉
谷歌有針對哈希的seo 但是依然不能跟以前的seo媲美 也沒人用。
history模式
只有一種情況可以使用那就是后端將所有前端路由都渲染同一個頁面,不管請求什么都得到同一個頁面,這個同一頁面不能是404
假設(shè)baidu.com/ ,/后面是啥都到首頁,就可以用history模式
使用條件:
1、后端知道將所有請求都渲染到同一個頁面
2、不用支持IE
缺點(diǎn):IE8一下不支持
history示例

window.location.pathname
console.log(window.location.pathname)
默認(rèn)就是/
注:
如果僅僅似是修改pathname
體驗會變差 每次點(diǎn)都要刷新 重新渲染
所以瀏覽器出了一個新的API 叫做history api
默認(rèn)number存在=/ 所以要if判斷
<a class="link" href="/1">go to 1</a>
---------------------------------------------------------------
const allA = document.querySelectorAll("a.link");
//上面這個方法拿到的allA是不能直接map的
//用這個方法取遍歷
for (let a of allA) {
a.addEventListener("click", e => {
e.preventDefault();
//得到a的href
const href = a.getAttribute("href");
//history 第一個參數(shù)似乎個對象 第二個參數(shù)是title 第三個是鏈接
//這里就是你之前是刷新去href我現(xiàn)在不讓你去了,我用下面這個方法去,路徑就會在不刷新頁面的情況下變更
window.history.pushState(null, `page ${href}`, href);//改變URL但不刷新頁面
// 通知 自己定義一個函數(shù)來代替之前的監(jiān)聽事件
onStateChange(href);
});
function onStateChange() {
console.log("state 變了");
route(app);
}
不用onStateChange也可以,當(dāng)window.history.pushState(null, `page ${href}`, href);之后我們頁面已經(jīng)跳轉(zhuǎn)了
但是之前的JS已經(jīng)執(zhí)行完了 但是它內(nèi)容還沒有渲染上來 所以必須再 route(app); 再次把內(nèi)容渲染上去
for (let a of allA) {
a.addEventListener("click", e => {
e.preventDefault();
const href = a.getAttribute("href");
window.history.pushState(null, `page ${href}`, href);
route(app);
});
}
memory 模式
hash 和 history 把數(shù)據(jù)都放在鏈接上
memory不一樣 存在localStorage
memory:用一個對象存儲你的東西,用到了localstorage 把路徑存到用戶看不到的地方
本示例 存到了xxx里面
window.localStorage.getItem("xxx")
就去看xxx是多少即可
把你要跳的東西存到xxx中
好處 適合非瀏覽器 app 里面的路由 他沒有路徑的呀
只能用memory模式
前面兩種都是把路徑存到URL里面 一個是哈希一個是路徑
memory不用URL 放哪里不關(guān)心 前端可能放localstorage
移動端可能放在本地數(shù)據(jù)庫
缺點(diǎn)就是沒有URL,只對單機(jī)有效
你進(jìn)入4了再把URL發(fā)給別人 那人家就獲取到的是初始狀態(tài)?。?br>
另外兩種URL記錄信息 分享的時候 頁面顯示幾 別人看到就是幾