前端路由那些事

樹醬但願將前端的樂趣帶給你們 本文已收錄 github.com/littleTreem… 喜歡就star✨html

談到路由,通常分爲前端路由和後端路由兩種,後端路由指的當用戶經過瀏覽器切換不一樣URL時,都會向服務器發起資源請求,服務器經過後端路由匹配以後根據不一樣URL返回不一樣頁面,而前端路由則將瀏覽器與服務器交互(頁面跳轉的URL規則匹配)的任務交給前端來作前端

1.前端路由模式

目前單頁應用(SPA)成爲目前前端應用的主流,而大型單頁應用的一個大特徵是,由前端路由來控制頁面的跳轉,經過url的切換,在不請求服務器的前提,更新頁面視圖,這裏以vue-router爲例分析,前端路由模式主要包括兩種:hash模式和history模式vue

1.1 hash 模式

hash模式便是經過 hash 值(相似錨點)的變化,瀏覽器不用向服務器發起請求,也就無需刷新頁面。而瀏覽器是怎麼監聽變化的呢?就是經過url中hash 值的變化,此時還好觸發 hashchange 事件,經過此事件的觸發咱們就能夠清晰知道hash發生了什麼變化html5

假設你瀏覽器訪問的url地址是 http://127.0.0.1/#/test 那麼經過 location.hash 獲取的hash值爲 #/testwebpack

致使路由的變化無非是三種狀況:刷新頁面、瀏覽器返回操做、新連接跳轉,下面是具體流程圖👇git

那hash模式下監聽路由變化實現的原理是怎麼樣的呢?github

window.addEventListener('hashchange', this.onHashChange.bind(this))
window.addEventListener('load', this.onHashChange.bind(this))
function onHashChange(){
// todo 匹配 hash 作 dom 更新操做
}
複製代碼

有興趣的童鞋能夠研究vue-router關於hash類的具體源碼實現 點我到達火箭web

1.2 history 模式

自HTML5新標準出臺,pushState和replaceState是HTML5的新接口,經過這兩個 API 能夠改變 url 地址且不會發送請求,前端路由今後了多了另一種模式History,並且經過這種模式再也不須要在URL添加#符號,也能讓URL顯得更加優美正則表達式

咱們先看看window.history對象裏面有什麼vue-router

History.pushState

在不刷新瀏覽器的狀況下,建立新的瀏覽記錄並插入瀏覽記錄隊列中,當刷新頁面,頁面內容不變但地址發生了變化,該API可傳入三個參數,分別是

  • 狀態對象(stateObject): 能夠經過pushState方法能夠將stateObject(對象)內容傳遞到新頁面中
  • 標題(title):可不傳
  • 地址(url):新的歷史記錄條目的地址(url不支持跨域);
window.history.pushState({data: "test"}, "", 'http://127.0.0.1/test');
複製代碼

History.replaceState:

的使用與 history.pushState() 相似,區別在於pushState會增長一條新的歷史記錄,而replaceState則會替換當前的歷史記錄,把當前的歷史記錄改爲目標地址

window.history.replaceState({data: "test"}, "", 'http://127.0.0.1/test');
複製代碼

popstate

當用戶發起返回操做或者執行history.go()或history.forward()等操做時,纔會觸發popstate

window.addEventListener('popstate', e => {
    //todo 
 });
複製代碼

講完history模式涉及到接口,樹醬聊聊配置history模式須要注意的事項,這種模式相比hash模式還須要配置後端,若是後臺沒有正確的配置,當用戶在瀏覽器直接刷新 http://127.0.0.1/#/test 就會返回 404,那如何解決這個問題呢 🤔️

你須要在Nginx配置文件添加劇定向 附上 history vue-router官方文檔

location / {
  try_files $uri $uri/ /index.html;
}
複製代碼

Vue-router History模式下的流程圖以下所示

有興趣Vue-router關於history類的具體源碼實現 點我到達火箭

2.路由應用

聊聊vue-router的一些應用場景

2.1 路由攔截

路由攔截能夠用來做爲前端鑑權入口,好比判斷是不是已登陸狀態

mport Vue from 'vue' import Router from 'vue-router' Vue.use(Router) const router = new Router({ routes: [ { path: '/home','' component: () => import('@/components/Home') } },{ path: '/login', name: 'login', component: (resolve) => { component: () => import('@/components/Login') } }}] }) // 判斷是否須要登陸權限 以及是否登陸 router.beforeEach((to, from, next) => { if (to.matched.some(res => res.meta.requireAuth)) { // 判斷路由是否須要登陸權限 if (localStorage.getItem('item')) { //判斷是否有token next() } else {// 沒登陸則跳轉到登陸界面 next({ path: '/login', query: {redirect: to.fullPath} }) } } else { next() } }) 複製代碼export default router 複製代碼

2.2 路由懶加載

懶加載,顧名思義就是等須要再加載,在SPA應用中,若是不經過懶加載加載組件的方式,會致使webpack打包出來的文件體制過大,進而影響用戶體驗

export default new Router({                                
  routes: [
    {
      path: '/home',                                            
      name: 'home',
      component: () => import('@/components/Home') # 懶加載引入組件
    }
  ]
});
複製代碼

2.3 路由模塊化管理

你是否還在煩惱如何按不一樣模塊不一樣功能管理不一樣路由,這裏要推薦使用 require.context()

不一樣功能模塊區分,再經過require.context 導出全部路由

require.context() 它容許傳入一個目錄進行搜索,一個標誌表示是否也應該搜索子目錄,以及一個正則表達式來匹配文件,當你構建項目時,webpack會處理require.context的內容

require.context()可傳入三個參數分別是:

  • directory :讀取文件的路徑

  • useSubdirectories :是否遍歷文件的子目錄

  • regExp: 匹配文件的正則

實際應用以下👇

routes導出來結果是這樣

固然本來的定義路由的方式也變了

/*
 * 我的中心路由模塊(user)
 * @Author: tree
 * @Date: 2019-11-06 20:20:51
 */
export default [
  {
    path: '/user/info',
    name: 'personalInfo',
    component: () => import('@/views/user/info.vue'),
    meta: { title: '帳號信息', keepAlive: false, showHeader: true },
  },
  {
    path: '/user/security',
    name: 'security',
    component: () => import('@/views/user/security.vue'),
    meta: { title: '安全設置', keepAlive: false, showHeader: true },
  },
];
複製代碼

2.4 其餘常見路由 API

  • window.history.back() : 加載 history 列表中的前一個 URL
  • window.history.forward() : 加載 history 列表中的下一個 URL
  • window.history.back(n) : 加載 history 列表中的某個頁面
  • window.location.href: 返回完整的URL
  • window.location.hash: 返回URL的錨部分
  • window.location.pathname: 返回URL路徑名

2.5 koa-router 待補充

相關文章
相關標籤/搜索