最近作項目才發現,我確實對 vue-router 太不熟悉了,都只瞭解個簡單用法就開始搞了,原本很簡單的問題,都搞不清楚。如今從新看一遍文檔,從新梳理一下。html
說實話,路由我一直也就光顧着用,沒認真思考過這個問題,仍是那次人家面試問了這個,我才反應過來是應該好好的瞭解一下了。前端
無刷新跳轉頁面,是單頁應用的一大優點,用戶體驗好,加載速度快,vue 路由的跳轉就是無刷新的,它有兩種形式,能夠在定義路由的時候經過 mode
字段去配置,若是不配置這個字段,那麼默認使用的就是 hash
模式。 hash 模式,即經過在連接後添加 # + 路由名字,根據匹配這個字段的變化,觸發 hashchange
事件,動態的渲染出頁面。就有點相似像 a 連接用做頁面上的錨點同樣,不會刷新頁面。vue
另一種方式,是 history
模式,也就是使用的瀏覽器的 history API,pushState
和 replaceState
。經過調用 pushState
操做瀏覽器的 history
對象,改變當前地址,同時結合window.onpopstate
監聽瀏覽器的返回和前進事件,一樣能夠實現無刷新的跳轉頁面。replaceState
與 pushStete
不一樣的就是,前者是替換一條記錄,後者是添加一條記錄。nginx
有關於 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
這個路徑,天然找不到啦~ajax
若是是 nginx 的服務器,在 location /
裏面加上 try_files $uri $uri/ /index.html;
便可。這行代碼表示:若是匹配不到靜態資源的路徑,就將重定向到 index 頁面,這樣就不會出錯啦~由於須要找後端小哥哥修改服務器配置文件,若是本身沒有徹底理解,兩邊又溝通不清楚的狀況下,使用 history 模式的難度無疑就大了一些~不過也不是什麼大問題~全看我的須要啦哈哈~算法
頁面參數無非就兩種,query 和 params,params 是以 /params
的形式表如今 url 上,而 query 是以 ?query=query1
這種形式表如今 url 上,此外,使用 params 參數還須要配置到路由定義上,否則不會展現在 url 上,而且刷新就會消失。vue-router
這個比較簡單,須要注意的地方就是:若是傳 params 參數,不能使用 path
字段跳轉,不然沒效果。而 query 參數則沒有這個限制,使用 name
和 path
字段均可以。 這個雖然簡單!可是必定要本身操做一遍才記得住啊。。反正我是早就看到,可是一直記混了~~從新用 demo 寫了一遍才記住~並且別人說的也不必定就是對的,仍是要本身實驗一遍才知道呢。╮(╯▽╰)╭編程
vue 路由的跳轉分紅兩種,一種是聲明式,使用<router-link>
聲明跳轉,to
屬性定義跳轉的參數。另外一種是編程式,使用 router.go()
、router.push()
、router.replace()
方法進行跳轉,go
方法就是與瀏覽器的history
api 的方法相同,能夠進行返回上一頁等操做。segmentfault
push
方法和replace
方法的區別在於,前者會把當前頁面加入 history 記錄裏面,能夠經過history.go(-1)
回到這個頁面。而replace
方法則會在 history 記錄裏面替換掉當前記錄,若是你在跳轉後的新頁面返回上一頁,它不會回到跳轉前的頁面,會回到上上個頁面,若是上上個頁面沒有記錄,則不會跳轉。
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)
—— 導航離開組件所在路由時被調用。最開始路由跳轉我都是用 push()
比較多,或者用 go()
作返回,不多用到過 replace()
,後來在業務需求下翻文檔才發現這個漏掉的 API。簡單來講,當你須要從A頁面跳轉到B頁面,再跳轉到C頁面,而後在C頁面返回,能直接返回到A頁面。那麼在B頁面跳轉C頁面的時候,使用replace()
方法進行跳轉便可。
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() // 這個方法必須調用 否則路由不會跳轉
}
複製代碼
在作微信受權跳轉的時候,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 比較簡單,主要的操做都在後端,前端只須要傳一個 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…