最近做專案才發現,我確實對 vue-router 太不熟悉了,都只瞭解個簡單用法就開始搞了,本來很簡單的問題,都搞不清楚。現在重新看一遍文件,重新梳理一下。
vue 路由的原理
說實話,路由我一直也就光顧著用,沒認真思考過這個問題,還是那次人家面試問了這個,我才反應過來是應該好好的瞭解一下了。
無重新整理跳轉頁面,是單頁應用的一大優勢,使用者體驗好,載入速度快,vue 路由的跳轉就是無重新整理的,它有兩種形式,可以在定義路由的時候通過 mode
欄位去配置,如果不配置這個欄位,那麼預設使用的就是 hash
模式。
hash 模式,即通過在連結後新增 # + 路由名字,根據匹配這個欄位的變化,觸發 hashchange
事件,動態的渲染出頁面。就有點類似像 a 連結用作頁面上的錨點一樣,不會重新整理頁面。
另外一種方式,是 history
模式,也就是使用的瀏覽器的 history API,pushState
和 replaceState
。通過呼叫 pushState
操作瀏覽器的 history
物件,改變當前地址,同時結合window.onpopstate
監聽瀏覽器的返回和前進事件,同樣可以實現無重新整理的跳轉頁面。replaceState
與 pushStete
不同的就是,前者是替換一條記錄,後者是新增一條記錄。
有關於 pushState
的用法,詳見MDN 文件。這個 API 與 ajax
合起來構成的 pjax
技術,也是用於實現頁面無重新整理載入的一種方式,常用於 PC 長列表頁面的翻頁啥的~
history 相對於 hash 模式來說,最大的好處就是沒有討厭的 # 符號,比如同樣一個 list 頁面,在 hash
模式下,url 連結表現為 http://yoursite.com/#/list
,看著就難受。在 history
模式下面,url 連結表現為 http://yoursite.com/list
,看著比較清爽~而且~相信做過微信公眾號開發的都懂,這個該死的 # 有多煩人~在下面的應用場景裡面我再講下這個問題~
那麼問題來了,既然 history 模式樣子好看,功能也一樣,為啥還是用 hash 模式的人比較多【此處沒有真憑實據,我瞎說的】?因為 history 模式,還需要服務端進行配置,否則重新整理頁面就會產生 404 錯誤。這裡也比較好理解啦,因為我們實際上是使用的 pushState 操作頁面的跳轉,而不是真的去伺服器請求另外一個 list.html 檔案,那按照 http://yoursite.com/#/list
這個路徑,自然找不到啦~
如果是 nginx 的伺服器,在 location /
裡面加上 try_files $uri $uri/ /index.html;
即可。這行程式碼表示:如果匹配不到靜態資源的路徑,就將重定向到 index 頁面,這樣就不會出錯啦~因為需要找後端小哥哥修改伺服器配置檔案,如果自己沒有完全理解,兩邊又溝通不清楚的情況下,使用 history 模式的難度無疑就大了一些~不過也不是什麼大問題~全看個人需要啦哈哈~
vue 路由傳參的兩種方式
頁面引數無非就兩種,query 和 params,params 是以 /params
的形式表現在 url 上,而 query 是以 ?query=query1
這種形式表現在 url 上,此外,使用 params 引數還需要配置到路由定義上,不然不會展示在 url 上,並且重新整理就會消失。
這個比較簡單,需要注意的地方就是:如果傳 params 引數,不能使用 path
欄位跳轉,否則沒效果。而 query 引數則沒有這個限制,使用 name
和 path
欄位都可以。
這個雖然簡單!但是一定要自己操作一遍才記得住啊。。反正我是早就看到,但是一直記混了~~重新用 demo 寫了一遍才記住~而且別人說的也不一定就是對的,還是要自己實驗一遍才知道呢。╮(╯▽╰)╭
vue 路由的跳轉
vue 路由的跳轉分成兩種,一種是宣告式,使用<router-link>
宣告跳轉,to
屬性定義跳轉的引數。另一種是程式設計式,使用 router.go()
、router.push()
、router.replace()
方法進行跳轉,go
方法就是與瀏覽器的history
api 的方法相同,可以進行返回上一頁等操作。
push
方法和replace
方法的區別在於,前者會把當前頁面加入 history 記錄裡面,可以通過history.go(-1)
回到這個頁面。而replace
方法則會在 history 記錄裡面替換掉當前記錄,如果你在跳轉後的新頁面返回上一頁,它不會回到跳轉前的頁面,會回到上上個頁面,如果上上個頁面沒有記錄,則不會跳轉。
vue 路由守衛
vue 路由守衛分為三種,一種是全域性的路由守衛,通常在例項化路由之後設定,來做一些通用的路由操作,它所有的路由跳轉都會執行的操作;一種是單個路由獨享的守衛,在單個路由定義的時候進行設定,所有跳轉這個路由都會執行;另外一種就是元件內的守衛,只在元件內生效。
全域性路由守衛型別:
router.beforeEach(to, from, next)
router.afterEach(to, from, next)
路由獨享的守衛:
beforeEnter(to, from, next)
元件獨享的守衛:
beforeRouteEnter(to, from, next)
beforeRouteUpdate(to, from, next)
—— 動態引數路徑改變時,元件例項被複用的時候呼叫。beforeRouteLeave(to, from, next)
—— 導航離開元件所在路由時被呼叫。
vue 路由的一些應用場景處理
什麼時候用 push,什麼時候用 replace
最開始路由跳轉我都是用 push()
比較多,或者用 go()
做返回,很少用到過 replace()
,後來在業務需求下翻文件才發現這個漏掉的 API。簡單來說,當你需要從A頁面跳轉到B頁面,再跳轉到C頁面,然後在C頁面返回,能直接返回到A頁面。那麼在B頁面跳轉C頁面的時候,使用replace()
方法進行跳轉即可。
動態改變頁面的 title
- 定義路由的時候,在路由的 meta 欄位裡面新增一個 title 屬性,定義好頁面的標題名稱。
- 在全域性的路由守衛
beforeEach()
方法裡面新增一個判斷,獲取路由的 meta 欄位,動態的改變頁面的 title。
// router.js
{
path: '/index',
name: 'index',
meta: {
title: '首頁'
}
}
// main.js
router.beforeEach(to, from, next){
if(to.meta.title){
document.title = to.meta.title
}
next() // 這個方法必須呼叫 不然路由不會跳轉
}
複製程式碼
微信開發,單頁應用頁面 url 導致的傳參或者跳轉失敗的問題
微信授權跳轉
在做微信授權跳轉的時候,hash 模式下連結裡面帶有 # 號可能會導致重定向跳轉失敗,使用 encodeURIComponent 把頁面地址處理之後,再傳入。
let _url = encodeURIComponent(location.href)
location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appid}&redirect_uri=${_url}&response_type=code&scope=snsapi_base&state=#wechat_redirect`
複製程式碼
獲取 wxconfig 配置
前端獲取 wxconfig 比較簡單,主要的操作都在後端,前端只需要傳一個 url 引數,由後端去獲取 config 的引數,回傳給前端。前端拿到引數後,呼叫 wx.config
方法。
let url = location.href.split('#')[0]
http.get('weixin/config',{
params:{
url: encodeURIComponent(url)
}
})
.then(res=>{
wx.config({
beta: true, // 必須這麼寫,否則wx.invoke呼叫形式的jsapi會有問題
debug: false, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
appId: res.data.appId, // 必填,企業微信的corpID
timestamp: res.data.timestamp, // 必填,生成簽名的時間戳
nonceStr: res.data.nonceStr, // 必填,生成簽名的隨機串
signature: res.data.signature,// 必填,簽名,見 附錄-JS-SDK使用許可權簽名演算法
jsApiList: ['scanQRCode'] // 必填,需要使用的JS介面列表,凡是要呼叫的介面都需要傳進來
})
// 檢測微信
wx.error(function(res){
// config資訊驗證失敗會執行error函式,如簽名過期導致驗證失敗,具體錯誤資訊可以開啟config的debug模式檢視,也可以在返回的res引數中檢視,對於SPA可以在這裡更新簽名。
console.log('錯誤資訊====',res)
})
})
複製程式碼
單頁面應用加百度統計
在單頁應用上面,如果直接把百度統計的程式碼加到 html 不做任何處理的話,是統計不到每個頁面的訪問量的,所以把新增 js 和 監聽跳轉頁面的程式碼都寫到 main.js 裡面去。
// 新增百度統計 先判斷是生產環境還是開發環境 如果是開發環境 不用新增
if (process.env.NODE_ENV !== 'development') {
let _hmt = _hmt || [];
window._hmt = _hmt; // 必須把_hmt掛載到window下,否則找不到
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?yourappid";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})()
}
router.beforeEach(to, from, next){
// 新增百度統計程式碼 先判斷是生產環境還是開發環境
if (process.env.NODE_ENV !== 'development') {
// 新增頁面統計
if (_hmt) {
if (to.path) {
_hmt.push(['_trackPageview', '/#' + to.fullPath]);
}
}
}
}
複製程式碼
參考文件:
segmentfault.com/a/119000001…
www.jianshu.com/p/febd38110…