vue-router 常用知識點二

目錄

- 1.vue-router 動態路由匹配

- 2.router-link組件及其屬性

- 3.vue-router路由的兩種模式

- 4.vue-router有哪幾種導航鉤子( 導航守衛 )?

- 5.完整的導航解析流程

- 6.vue-router實現路由懶加載( 動態加載路由 )參考http://www.lxweimin.com/p/a88a2ae4ebde


- 1. vue-router 動態路由匹配

我們經常需要把某種模式匹配到的所有路由,全都映射到同個組件。例如,我們有一個 User 組件,對于所有 ID 各不相同的用戶,都要使用這個組件來渲染。那么,我們可以在 vue-router 的路由路徑中使用“動態路徑參數”(dynamic segment) 來達到這個效果:

const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 動態路徑參數 以冒號開頭
    { path: '/user/:id', component: User }
  ]
})

現在呢,像 /user/foo/user/bar 都將映射到相同的路由。

一個“路徑參數”使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到 this.$route.params,可以在每個組件內使用。于是,我們可以更新 User 的模板,輸出當前用戶的 ID:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

你可以看看這個在線例子。

你可以在一個路由中設置多段“路徑參數”,對應的值都會設置到 $route.params 中。例如:

模式 匹配路徑 $route.params
/user/:username /user/evan { username: 'evan' }
/user/:username/post/:post_id /user/evan/post/123 { username: 'evan', post_id: '123' }

除了 $route.params 外,$route 對象還提供了其它有用的信息,例如,$route.query (如果 URL 中有查詢參數)、$route.hash 等等。你可以查看 API 文檔 的詳細說明。

- 2. router-link組件及其屬性

支持用戶在具有路由功能的應用中 (點擊) 導航 通過 to 屬性指定目標地址
一:router-link組件的props:

  • to

表示目標路由的鏈接。當被點擊后,內部會立刻把 to 的值傳到 router.push()

<router-link :to='/Home'>Home</router-link>
渲染結果:
<a href="Home">Home</a>
<router-link :to="{ path: 'register', query: { name: 'fjw' }}">router</router-link>
渲染結果:
<a href="/register?name=fjw">router</a>
  • tag:

指定<router-link>組件最終被渲染成什么標簽;非必須;如果沒有tag屬性,router-link最終會被渲染成a標簽。在上面的栗子中,渲染成了li標簽。

<router-link :to='/Home' tag="li" >Home</router-link>
渲染結果:
<li>Home</li>
此時依舊會監聽點擊事件,觸發導航
  • replace:

當點擊時,會調用 router.replace() 而不是 router.push(),于是導航后不會留下 history 記錄。

<router-link :to="{ path: '/abc'}" replace></router-link>
  • append:

則在當前 (相對) 路徑前添加基路徑。/a 導航到一個相對路徑 b,如果沒有配置 append,則路徑為 /b,如果配了,則為 /a/b

<router-link :to="{ path: 'relative/path'}" append></router-link>
  • active-class:

  • 表示激活這個鏈接時,添加的class,默認是router-link-class。默認值可以通過路由的構造選項 linkActiveClass 來全局配置。
  • exact:

"是否激活" 默認類名的依據是 inclusive match (全包含匹配)。

<!-- 這個鏈接只會在地址為 / 的時候被激活 -->
<router-link to="/" exact>
  • event:

默認值: 'click' 聲明可以用來觸發導航的事件??梢允且粋€字符串或是一個包含字符串的數組。

  • exact-active-class:

默認值: "router-link-exact-active" 配置當鏈接被精確匹配的時候應該激活的 class。

- 3.vue-router路由的兩種模式mode

  • 類型: string

  • 默認值: "hash" (瀏覽器環境) | "abstract" (Node.js 環境)

  • 可選值: "hash" | "history" | "abstract"

    配置路由模式:

    • hash: 使用 URL hash 值來作路由。支持所有瀏覽器,包括不支持 HTML5 History Api 的瀏覽器。

    • history: 依賴 HTML5 History API 和服務器配置。查看 HTML5 History 模式。

    • abstract: 支持所有 JavaScript 運行環境,如 Node.js 服務器端。如果發現沒有瀏覽器的 API,路由會自動強制進入這個模式

  • hash模式:

url 的 hash 是以 # 開頭,原本是用來作為錨點,從而定位到頁面的特定區域。當 hash 改變時,頁面不會因此刷新,瀏覽器也不會向服務器發送請求。
http://www.xxx.com/#/home
同時, hash 改變時,并會觸發相應的 hashchange 事件。所以,hash 很適合被用來做前端路由。當 hash 路由發生了跳轉,便會觸發 hashchange 回調,回調里可以實現頁面更新的操作,從而達到跳轉頁面的效果。
hash模式的工作原理是hashchange事件,可以在window監聽hash的變化。我們在url后面隨便添加一個#xx觸發這個事件。

  window.onhashchange = function(event){
    console.log(event);
  }

image

可以看到里邊有兩個屬性newURL和oldURL??梢酝ㄟ^模擬改變hsh的值,動態頁面數據。

<div id="test" style="height: 500px;width: 500px;margin: 0 auto"></div>
<script>
  window.onhashchange = function(event){
    let hash = location.hash.slice(1);
    document.body.style.color = hash;
    document.getElementById('test').style.backgroundColor = hash
  }
</script>

image

盡管瀏覽器沒有請求服務器,但是頁面狀態和url已經關聯起來了,這就是所謂的前端路由,單頁應用的標配。

  • history模式:

HTML5 規范中提供了 history.pushState 和 history.replaceState 來進行路由控制。通過這兩個方法,可以實現改變 url 且不向服務器發送請求。同時不會像 hash 有一個 # ,更加的美觀。但是 History 路由需要服務器的支持,并且需將所有的路由重定向到根頁面。

History 路由的改變不會去觸發某個事件,所以我們需要去考慮如何觸發路由更新后的回調。

有以下兩種方式會改變 url:

  • 調用 history.pushState 或 history.replaceState;
  • 點擊瀏覽器的前進與后退。

第一個方式可以封裝一個方法,在調用 pushState(replaceState)后再調用回調。

function push (url) {
 window.history.pushState({}, null, url);
 handleHref();
}
 
function handleHref () {
 console.log('render');
}

第二個方式,瀏覽器的前進與后退會觸發 popstate 事件。

window.addEventListener('popstate', handleHref);
image

前進,后退,跳轉操作方法:

  history.go(-3);//后退3次
  history.go(2);//前進2次
  history.go(0);//刷新當前頁面
  history.back(); //后退
  history.forward(); //前進

https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90

這篇文章介紹的較為詳細,講到了實現原理https://juejin.im/post/5b330142e51d4558b10a9cc5

- 4.vue-router有哪幾種導航鉤子( 導航守衛 )?

vue-router 提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。
例如判斷登錄信息:沒登錄全部跳到登錄頁。判斷必要操作是否進行沒進行的話中斷跳轉。
參數或查詢的改變并不會觸發進入/離開的導航守衛。你可以通過觀察 $route 對象來應對這些變化,或使用 beforeRouteUpdate 的組件內守衛。

分為三大類:全局守衛、路由守衛、組件守衛

[#]全局前置守衛

你可以使用 router.beforeEach 注冊一個全局前置守衛:

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

當一個導航觸發時,全局前置守衛按照創建順序調用。守衛是異步解析執行,此時導航在所有守衛 resolve 完之前一直處于 等待中。
每個守衛方法接收三個參數:

  • to: Route: 即將要進入的目標 路由對象

  • from: Route: 當前導航正要離開的路由

  • next: Function: 一定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。

    • next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。

    • next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應的地址。

    • next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向 next 傳遞任意位置對象,且允許設置諸如 replace: true、name: 'home' 之類的選項以及任何用在 router-linkto proprouter.push 中的選項。

    • next(error): (2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 注冊過的回調。

確保要調用 next 方法,否則鉤子就不會被 resolved。

#全局解析守衛

在 2.5.0+ 你可以用 router.beforeResolve 注冊一個全局守衛。這和 router.beforeEach 類似,區別是在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用。

#全局后置鉤子

你也可以注冊全局后置鉤子,然而和守衛不同的是,這些鉤子不會接受 next 函數也不會改變導航本身:

router.afterEach((to, from) => {
  // ...
})

#路由獨享的守衛

你可以在路由配置上直接定義 beforeEnter 守衛:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

這些守衛與全局前置守衛的方法參數是一樣的。

#組件內的守衛

最后,你可以在路由組件內直接定義以下路由導航守衛:

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 因為當守衛執行前,組件實例還沒被創建
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,但是該組件被復用時調用
    // 舉例來說,對于一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。
    // 可以訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
    // 可以訪問組件實例 `this`
  }
}

beforeRouteEnter 守衛 不能 訪問 this,因為守衛在導航確認前被調用,因此即將登場的新組件還沒被創建。

不過,你可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回調,并且把組件實例作為回調方法的參數。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通過 `vm` 訪問組件實例
  })
}

注意 beforeRouteEnter 是支持給 next 傳遞回調的唯一守衛。對于 beforeRouteUpdatebeforeRouteLeave 來說,this 已經可用了,所以不支持傳遞回調,因為沒有必要了。

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}

這個離開守衛通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過 next(false) 來取消。

beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

#完整的導航解析流程

  1. 導航被觸發。
  2. 在失活的組件里調用離開守衛。
  3. 調用全局的 beforeEach 守衛。
  4. 在重用的組件里調用 beforeRouteUpdate 守衛 (2.2+)。
  5. 在路由配置里調用 beforeEnter
  6. 解析異步路由組件。
  7. 在被激活的組件里調用 beforeRouteEnter。
  8. 調用全局的 beforeResolve 守衛 (2.5+)。
  9. 導航被確認。
  10. 調用全局的 afterEach 鉤子。
  11. 觸發 DOM 更新。
  12. 用創建好的實例調用 beforeRouteEnter 守衛中傳給 next 的回調函數。
圖片描述
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 回憶: 我們知道,h5的history或者hash幫助我們解決了,變化url跳轉頁面不發送請求,并且我們能監聽到u...
    LoveBugs_King閱讀 3,674評論 0 5
  • 前言 vue-router是什么:是vue.js官方的路由管理器和vue.js的核心深度的集成,讓開發者更加簡單的...
    GUAN_one閱讀 3,746評論 0 2
  • 學習目的 學習Vue的必備技能,必須 熟練使用 Vue-router,能夠在實際項目中運用。 Vue-rout...
    _1633_閱讀 92,451評論 3 58
  • 介紹 vue-router是一個vue插件。其實質是在location.hash、location.replace...
    AmazRan閱讀 1,596評論 0 6
  • 第一次畫這種杯子蛋糕,畫之前怕畫不好,畫完效果還可以,濃濃的巧克力,滿滿的甜蜜誘惑,畫吃的最不好的一點就是畫著畫著...
    夢浮荏閱讀 2,033評論 3 13