這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 眾所周知,vue路由模式常見的有 history 和 hash 模式,但其實還有一種方式-abstract模式(瞭解一哈~) 別急,本文我們將重點逐步瞭解: 路由 + 幾種路由模式 + 使用場景 + 思考 + freestyle 路由概念 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
眾所周知,vue路由模式常見的有 history 和 hash 模式,但其實還有一種方式-abstract模式(瞭解一哈~)
別急,本文我們將重點逐步瞭解: 路由 + 幾種路由模式 + 使用場景 + 思考 + freestyle
路由概念
路由的本質就是一種對應關係,根據不同的URL請求,返回對應不同的資源。那麼url地址和真實的資源之間就有一種對應的關係,就是路由。
路由模式由來
對於 Vue 這類漸進式前端開發框架,為了構建 SPA(單頁面應用),需要引入前端路由系統,這也就是 Vue-Router 存在的意義。而前端路由的核心,就在於 —— 改變視圖的同時不會向後端發出請求。
為了達到這一目的,就產生了我們的 —— 路由模式
三種路由模式詳解
hash模式
示例: www.ikun.com/#/kun,hash 的值為 #/kun。
概述:
地址欄 URL 中有 # 符號,後面就是 hash 值的變化(此 hash 不是密碼學里的散列運算)。特點是:hash 雖然出現在 URL 中,但不會被包括在 HTTP 請求中,對後端沒有影響,改變後面的 hash 值,它不會向伺服器發出請求,因此也就不會 刷新頁面/重新載入頁面。
每次 hash 值發生改變的時候,會觸發 hashchange 事件。因此我們可以通過監聽該事件,來知道 hash 值發生了哪些變化。
window.addEventListener('hashchange', ()=>{ // 通過 location.hash 獲取到最新的 hash 值 console.log(location.hash); });使用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>hash路由</title> </head> <body> <ul> <!-- 通過標簽導航 聲明式導航 --> <!-- location.href='#/home' js方式進行導航切換 編程式導航 --> <li><a href="#/home">首頁</a></li> <li><a href="#/about">關於</a></li> </ul> <div id="routerView"></div> <script> const routerRender = () => { // 每次都置空hash let html = '' // 根據地址欄hash值的不同返回對應的資源 try { // 如果hash值為空就給一個home let hash = location.hash || '#/home' html = component[hash.slice(2)]() } catch (error) { html = `<div>404</div>` } // 渲染到頁面上 document.getElementById('routerView').innerHTML = html } const component = { home() { return `<div>home頁面</div>` }, about() { return '<div>關於頁面</div>' } } window.onload = function () { routerRender() } // 事件,監聽地址欄中的hash值變化,實現回退 window.addEventListener('hashchange', routerRender) </script> </body> </html>
優缺點:
優點:hash模式相容性、安全性很強,刷新瀏覽器,頁面還會存在
缺點:地址欄不優雅,有#存在,不利於seo,記憶困難
註意:
hash 模式既可以通過聲明式導航,也可以通過編程式導航,上面的案例展示的是聲明式導航。而下麵將要講到的 history 模式只能通過編程式導航實現,因為 history 是 js 對象。
history模式
示例: www.ikun.com/kun,地址欄中沒有#,
路由地址跟正常的url一樣
概述:
history —— 利用了 HTML5 History API 為瀏覽器的全局 history 對象增加的 pushState() 和 replaceState() 方法,可以對瀏覽器歷史記錄棧進行修改。(新增特性,所以瀏覽器需考慮IE9以及以下的版本帶來的問題)。當地址欄的history狀態發生變化時 切換了router-view渲染的組件 來"欺騙"用戶 到達切換新網頁的效果,需要後端配合。
History 還包括back、forward、go三個方法,對應瀏覽器的前進,後退,跳轉操作。就是瀏覽器左上角的前進、後退等按鈕進行的操作。
history.go(-2);//後退兩次 history.go(2);//前進兩次 history.back(); //後退 hsitory.forward(); //前進
只要歷史棧有信息發生改變的話,window對象中提供的 popstate 事件就會監聽到歷史棧的改變,就會觸發該事件。
history.pushState({},title,url); // 向歷史記錄中追加一條記錄 history.replaceState({},title,url); // 替換當前頁在歷史記錄中的信息。 window.addEventListener('popstate', function(e) { console.log(e) })
使用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>history模式</title> </head> <body> <ul> <li><a href="/home">首頁</a></li> <li><a href="/about">關於</a></li> </ul> <div id="routerView"></div> <script> const component = { home() { return `<div>home頁面</div>` }, about() { return '<div>關於頁面</div>' } } const routerRender = pathname => { let html = '' try { html = component[pathname]() } catch (error) { html = `<div>404</div>` } document.getElementById('routerView').innerHTML = html } // history模式,它的路由導航,只能通過js來完成 , history它是js對象 // 給鏈接添加點擊事件 document.querySelectorAll('a').forEach(node => { node.addEventListener('click', function (evt) { // 阻止a標簽的預設跳轉行為 evt.preventDefault() // 跳轉到指定的地址,能回退 // history.pushState // 跳轉到指定持址,不能回退 // history.replaceState history.pushState({}, null, this.href) // 渲染 routerRender(this.href.match(//(\w+)$/)[1]) }) }) // 在網頁載入完畢後立刻執行的操作,即當 HTML 文檔載入完畢後,立刻渲染 home 中的標簽 window.onload = () => { routerRender('home') } // 回退 window.addEventListener('popstate', function () { routerRender(location.pathname.slice(1)) }) </script> </body> </html>
優缺點:
缺點:history模式,相容性較差,刷新頁面,頁面會404,需要伺服器端配置支持
優點:地址欄更優雅,方便記憶,有利於有seo
刷新頁面出現404原因以及解決:
原因:
因為vue項目中路由hash模式改為了history模式,由於hash模式時url帶的#號後面是哈希值不會作為url的一部分發送給伺服器,而history模式下當刷新頁面之後瀏覽器會直接去請求伺服器,而伺服器沒有這個路由,於是就出現404。
因為我們的應用是單頁客戶端應用,當使用 history 模式時,URL 就像正常的 url,可以直接訪問www.ikun.com/kun/love,但是因為 vue-router 設置的路徑不是真實存在的路徑,所以刷新就會返回404錯誤
解決方法(後端配合,這裡講的是nginx配置):
在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。也就是在服務端修改404錯誤頁面的配置路徑,讓其指向到index.html
方法一:
location /{ root /data/nginx/html; index index.html index.htm; if (!-e $request_filename) { rewrite ^/(.*) /index.html last; break; } }
方法二: (vue.js官方教程里提到的https://router.vuejs.org/zh-cn/essentials/history-mode.html)
server { listen 8888;#預設埠是80,如果埠沒被占用可以不用修改 server_name localhost; root E:/vue/my_project/dist;#vue項目的打包後的dist location / { try_files $uri $uri/ @router;#需要指向下麵的@router否則會出現vue的路由在nginx中刷新出現404 index index.html index.htm; } #對應上面的@router,主要原因是路由的路徑資源並不是一個真實的路徑,所以無法找到具體的文件 #因此需要rewrite到index.html中,然後交給路由在處理請求資源 location @router { rewrite ^.*$ /index.html last; } #.......其他部分省略 }
abstract模式
abstract模式----適用於所有JavaScript環境,例如伺服器端使用Node.js。如果沒有瀏覽器API,路由器將自動被強制進入此模式。
abstract 是一種與瀏覽器分離的路由模式,本身是用來在不支持瀏覽器API的環境中,充當fallback,而不論是hash還是history模式都會對瀏覽器上的url產生作用。
利用abstract這種與瀏覽器分離的路由模式,我們可以在已存在的路由頁面中內嵌其他的路由頁面,而保持在瀏覽器當中依舊顯示當前頁面的路由path。
使用場景
history --- 顏值性(強迫症患者推薦,更友好的URL格式、SEO支持)
一般場景下,hash 和 history 都可以,除非你更在意顏值,# 符號夾雜在 URL 里看起來確實有些不太美麗。我們可以用路由的 history 模式,充分利用 history.pushState API 來完成URL 跳轉而無須重新載入頁面。如果需要更好的SEO支持,並且願意進行伺服器端配置,history 模式是很好的選擇
調用 history.pushState() 相比於直接修改 hash,還存在以下優勢:
1、pushState() 設置的新 URL 可以是與當前 URL 同源的任意 URL;而 hash 只可修改 #後面的部分,因此只能設置與當前 URL 同文檔的 URL;
2、pushState() 設置的新 URL 可以與當前 URL 一模一樣,這樣也會把記錄添加到棧中;而 hash設置的新值必須與原來不一樣才會觸發動作將記錄添加到棧中;
3、pushState() 通過 stateObject 參數可以添加任意類型的數據到記錄中;而 hash 只可添加短字元串;
4、pushState() 可額外設置 title 屬性供後續使用。
hash ---- 安全相容,不需要後端協助
SPA 雖然在瀏覽器里游刃有餘,但真要通過 URL 向後端發起 HTTP 請求時,兩者的差異就來了。尤其在用戶手動輸入 URL 後回車,或者刷新(重啟)瀏覽器的時候。
hash 模式下,僅 hash 符號之前的內容會被包含在請求中,如 www.ikun.com ,因此對於後端來說,即使沒有做到對路由的全覆蓋,也不會返回 404 錯誤。
abstract模式 ---- 特殊場景
abstract模式----適用於所有JavaScript環境(瀏覽器端和服務端),例如伺服器端使用Node.js。
像上文說的,可以利用abstract這種與瀏覽器分離的路由模式,在已存在的路由頁面中內嵌其他的路由頁面,而保持在瀏覽器當中依舊顯示當前頁面的路由path。
小結
選擇使用 hash 模式還是 history 模式,主要取決於你的具體需求和項目要求。如果你的應用不需要考慮SEO,並且不涉及伺服器端的重定向和處理,Hash模式是一種簡單且易於使用的選擇。如果你需要更友好的URL格式、更好的SEO支持,並且願意進行伺服器端配置,那麼history 模式是更好的選擇。
結合自身例子,對於一般形式的 Web 開發場景,個人比較習慣用用 history 模式,只需在後端(Apache 或 Nginx)進行簡單的路由配置,同時搭配前端路由的 404 頁面支持。