Vue的路由及路由鉤子函數

Vue的路由及路由鉤子函數

什麼是路由

什麼是路由?網絡原理中,路由指的是根據上一接口的數據包中的IP地址,查詢路由錶轉發到另外一個接口,它決定的是一個端到端的網絡路徑。
web中,路由的概念也是相似,根據URL來將請求分配到指定的一個'端'。(即根據網址找到能處理這個URL的程序或模塊)
使用vue.js構建項目,vue.js自己就能夠經過組合組件來組成應用程序;當引入vue-router後,咱們須要處理的是將組件(components)映射到路由(routes),而後在須要的地方進行使用渲染。javascript

其所包含的功能有:html

  • 嵌套的路由/視圖表
  • 模塊化的、基於組件的路由配置
  • 路由參數、查詢、通配符
  • 基於 Vue.js 過渡系統的視圖過渡效果
  • 細粒度的導航控制
  • 帶有自動激活的 CSS class 的連接
  • HTML5 歷史模式或 hash 模式,在 IE9 中自動降級
  • 自定義的滾動條行爲

一、基礎路由

當咱們經過 vue create 建立項目的的時候,會選擇是否安裝vue-router,項目建立後,在主組件App.vue中的HTML部分:vue

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 組件來導航. -->
    <!-- 經過傳入 `to` 屬性指定連接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的組件將渲染在這裏 -->
  <router-view></router-view>
</div>

上述代碼中,<router-view/>是路由出口,路由匹配到的組件將渲染在這裏。java

二、在router/index.js文件中

// 0. 若是使用模塊化機制編程,導入Vue和VueRouter,要調用 Vue.use(VueRouter)

// 1. 定義 (路由) 組件。 能夠從其餘文件 import 進來
const Foo = { template: '<div>foo</div>' }

// 2. 定義路由每一個路由應該映射一個組件。 其中"component" 能夠是經過 Vue.extend() 建立的組件構造器,或者,只是一個組件配置對象。

const routes = [
  { path: '/foo', component: Foo },
 
]

// 3. 建立 router 實例,而後傳 `routes` 配置
const router = new VueRouter({
  routes 
})

// 4. 建立和掛載根實例。經過 router 配置參數注入路由,從而讓整個應用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

三、動態路由

什麼是動態路由?動態路由是指路由器可以自動的創建本身的路由表,而且可以根據實際狀況的變化實時地進行調整。
一、在vue項目中,使用vue-router若是進行不傳遞參數的路由模式,則稱爲靜態路由;若是可以傳遞參數,對應的路由數量是不肯定的,此時的路由稱爲動態路由。動態路由,是以冒號爲開頭的(:),例子以下:web

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }, {
      path: '/RouterComponents/:id',
      name: 'RouterComponents',
      component: RouterComponents
    }
  ]
})

一個「路徑參數」使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到 this.$route.params,能夠在每一個組件內使用。vue-router

二、路由跳轉,執行方式有兩大類;
第一大類:router-link模式,直接把參數寫在to屬性裏面:編程

<router-link :to="{name:'RouterComponents',params:{id:110}}">跳轉</router-link>

第二大類:$router.push()模式,代碼以下:瀏覽器

methods: {
    changeFuc (val) {
      this.$router.push({
        name: 'RouterComponents',
        params: {id: val}
      })
    }
}

或者:服務器

methods: {
    changeFuc (val) {
      this.$router.push({
        path: `/RouterComponents/${val}`,
      })
    }
}

四、路由嵌套

vue項目中,界面一般由多個嵌套的組件構成;同理,URL中的動態路由也能夠按照某種結構對應嵌套的各層組件:網絡

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        {
          // 當 /user/:id/profile 匹配成功,
          // UserProfile 會被渲染在 User 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 當 /user/:id/posts 匹配成功
          // UserPosts 會被渲染在 User 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

五、捕獲全部路由或404 NotFound路由

常規參數只會匹配被 / 分隔的 URL 片斷中的字符。若是想匹配任意路徑,咱們可使用通配符 (*):

{
  // 會匹配全部路徑
  path: '*'
}
{
  // 會匹配以 `/user-` 開頭的任意路徑
  path: '/user-*'
}

當使用通配符路由時,請確保路由的順序是正確的,也就是說含有通配符的路由應該放在最後。路由 { path: '*' } 一般用於客戶端 404 錯誤。若是你使用了History 模式,請確保正確配置你的服務器

六、編程式導航

聲明式 編程式
<router-link :to="..."> router.push(...)

想要導航到不一樣的 URL,則使用 router.push 方法。這個方法會向 history 棧添加一個新的記錄,因此,當用戶點擊瀏覽器後退按鈕時,則回到以前的 URL。

當你點擊 <router-link> 時,這個方法會在內部調用,因此說,點擊 <router-link :to="..."> 等同於調用 router.push(...)

// 字符串
router.push('home')

// 對象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

若是提供了 path,params 會被忽略

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 這裏的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

七、命名路由

因爲咱們須要經過不一樣的路由跳轉到不一樣的頁面,這時給咱們的路由都加一個名字操做起來會比較方便

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

八、命名視圖

有時候咱們須要一個佈局,這時候,咱們就須要用到命名視圖。

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

九、嵌套命名視圖

{
  path: '/settings',
  // 你也能夠在頂級路由就配置命名視圖
  component: UserSettings,
  children: [{
    path: 'emails',
    component: UserEmailsSubscriptions
  }, {
    path: 'profile',
    components: {
      default: UserProfile,
      helper: UserProfilePreview
    }
  }]
}

十、路由組件傳參

在組件中使用 $route 會使之與其對應路由造成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。

使用 props 將組件和路由解耦:

取代與 $route 的耦合

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

經過 props 解耦

const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, props: true },

    // 對於包含命名視圖的路由,你必須分別爲每一個命名視圖添加 `props` 選項:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

路由鉤子

一、路由鉤子

在某些狀況下,當路由跳轉前或跳轉後、進入、離開某一個路由前、後,須要作某些操做,就可使用路由鉤子來監聽路由的變化

全局路由鉤子:router.beforeEach 註冊一個全局前置守衛

router.beforeEach((to, from, next) => {
    //會在任意路由跳轉前執行,next必定要記着執行,否則路由不能跳轉了
  console.log('beforeEach')
  console.log(to,from)
  //
  next()
})
//
router.afterEach((to, from) => {
    //會在任意路由跳轉後執行
  console.log('afterEach')
})

單個路由鉤子:
只有beforeEnter,在進入前執行,to參數就是當前路由

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

路由組件鉤子:

beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 由於當守衛執行前,組件實例還沒被建立
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,可是該組件被複用時調用
    // 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。
    // 能夠訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
    // 能夠訪問組件實例 `this`
  }

附:完整的導航解析流程

  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 的回調函數。

二、路由元信息

定義路由的時候能夠配置 meta 字段:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})
相關文章
相關標籤/搜索