vue-router再學習

vue路由:html

1:動態路由配置

import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/view/index'
import Layout from '@/view/layout'
import Home from '@/view/home'
import error from '@/view/error'
import p404 from '@/view/404'
import p505 from '@/view/505'
import Login from '@/login'
import AddGood from '@/view/table/addGoods'

Vue.use(Router)

const router = new Router({
  routes: [
    {path:'/',redirect:'/home'},
    {
      path: '/',
      name: 'Index',
      component: Index,
      children:[
        {
          path: 'home',
          name: 'Home',
          component: Home,
          meta:{
            requireLogin:true
          },
        },
        {
          path: 'add',
          name: 'AddGood',
          component: AddGood,
          meta:{
            requireLogin:true
          },
        }
      ]
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/error',
      name: 'error',
      component: error,
      children:[
        {
          path: '404',
          name: '404',
          component: p404,
        },
        {
          path: '505',
          name: '505',
          component: p505,
        }

      ]
    }
  ]
})
// 路由攔截
router.beforeEach((to, from, next) => {
  if (to.matched.some(res => res.meta.requireLogin)) {
    // 判斷是否須要登陸權限
    if (window.localStorage.getItem("username")) {
      next();
    } else {
      // 沒登陸則跳轉到登陸界面
      console.log("to login");

      next({
        path: "/login"
      });
    }
  } else {
    next();
  }
});
export default router;

2:響應路由參數的變化:

例如從/user/foo導航到/user/bar,原來的組件會被複用,
這種方式獲取url上的參數能夠watch來監視$route對象來獲取

3:嵌套路由:要在嵌套的出口中渲染組件,須要在 VueRouter 的參數中使用 children 配置:

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
        }
      ]
    }
  ]
})

路由能夠層層嵌套;要注意,以 / 開頭的嵌套路徑會被看成根路徑。 這讓你充分的使用嵌套組件而無須設置嵌套的路徑。vue

當你訪問一個沒有匹配的路由的時候,若是要渲染點什麼東西,能夠提供一個空的子路由vue-router

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

        // ...其餘子路由
      ]
    }
  ]
})

### 4:編程式導航:router.push(location, onComplete?, onAbort?)編程

除了使用 <router-link> 建立 a 標籤來定義導航連接,咱們還能夠藉助 router 的實例方法,經過編寫代碼來實現。
注意:在 Vue 實例內部,你能夠經過 $router 訪問路由實例。所以你能夠調用 this.$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' }})
這裏的命名是指在route.JS裏面定義動態路由配置name,參考第一點

帶查詢參數:變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:若是提供了path,則params會被忽略,所以不能這樣寫:
this.$router.push({ path: 'register', params: { plan: 'private' }})這樣是不能解析參數出來的。
正確的寫法應該是這樣:
this.$router.push({path:`user/${userID}`})  ===> /user/123,
this.router.push({path:'user',params:{userID}}) ====> /user,不能解析出userID
注意跟命名路由的區別:
this.$router.push({name:'user',params:{userId: 123}})===> /user/123

用於記住導航連接:在 2.2.0+,可選的在 router.pushrouter.replace 中提供 onCompleteonAbort 回調做爲第二個和第三個參數。這些回調將會在導航成功完成 (在全部的異步鉤子被解析以後) 或終止 (導航到相同的路由、或在當前導航完成以前導航到另外一個不一樣的路由) 的時候進行相應的調用。瀏覽器

注意: 若是目的地和當前路由相同,只有參數發生了改變 (好比從一個用戶資料到另外一個 /users/1 -> /users/2),你須要使用 beforeRouteUpdate 來響應這個變化 (好比抓取用戶信息)。異步

router.go(n):this.$router.go(-1)後退1步 this.$router.go(1)前進1步 .....等價於window.history.go(n)。

5.命名路由:

命名路由即在routes配置裏面增長一個name屬性來做爲路由名稱
const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})

連接的時候router-link 的 to 屬性傳一個對象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
或者在js裏面:router.push({ name: 'user', params: { userId: 123 }})

命名視圖

改功能不多用到:通常用於不一樣用戶不一樣視圖的狀況(能夠用來作PC端和移動端的切換)
若有三個同級視圖
<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>
一個視圖使用一個組件渲染,所以對於同個路由,多個視圖就須要多個組件。確保正確使用 components 配置 (帶上 s):
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

重定向:

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})
或命名路由
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

或者方法
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目標路由 做爲參數
      // return 重定向的 字符串路徑/路徑對象
    }}
  ]
})

別名

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})
訪問/a時url時/a,訪問/b時,url爲/a
「別名」的功能讓你能夠自由地將 UI 結構映射到任意的 URL,而不是受限於配置的嵌套路由結構。

關於路由參數的傳遞:

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

經過props解耦
 props: ['id'](和data平級)
 
對象模式:(不多用)
若是 props 是一個對象,它會被按原樣設置爲組件屬性。當 props 是靜態的時候有用。
const router = new VueRouter({
  routes: [
    { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
  ]
})

函數模式(不多用)建立一個函數返回 props。這樣你即可以將參數轉換成另外一種類型,將靜態值與基於路由的值結合等等。
const router = new VueRouter({
  routes: [
    { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
  ]
})

高級應用:ide

路由守衛:函數

可使用 router.beforeEach 註冊一個全局前置守衛:
const router = new VueRouter({ 
    routes:[
      .....
    ]
})

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-link 的 to prop 或 router.push 中的選項。

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

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


2.5.0+ 新增
全局解析守衛
    在 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) => {
        // ...
      }
    }
  ]
})

完整的導航解析流程

  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 }
        }
      ]
    }
  ]
})
那麼如何訪問這個 meta 字段呢?須要遍歷 $route.matched 來檢查路由記錄中的 meta 字段。
全局導航守衛中檢查元字段:
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 確保必定要調用 next()
  }
})

過渡效果:詳情參考https://cn.vuejs.org/v2/guide/transitions.html

<router-view> 是基本的動態組件,因此咱們能夠用 <transition> 組件給它添加一些過渡效果:post

單個路由的過渡:在各路由組件內使用 <transition> 並設置不一樣的 name。

const Foo = {
  template: `
    <transition name="slide">
      <div class="foo">...</div>
    </transition>
  `
}

const Bar = {
  template: `
    <transition name="fade">
      <div class="bar">...</div>
    </transition>
  `
}

基於路由的動態過渡

<!-- 使用動態的 transition name -->
<transition :name="transitionName">
  <router-view></router-view>
</transition>

// 接着在父組件內
// watch $route 決定使用哪一種過渡
watch: {
  '$route' (to, from) {
    const toDepth = to.path.split('/').length
    const fromDepth = from.path.split('/').length
    this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
  }
}

導航完成後獲取數據:通常在created鉤子發送請求fetch

created () {
    // 組件建立完後獲取數據,
    // 此時 data 已經被 observed 了
    this.fetchData()
  },
  watch: {
    // 若是路由有變化,會再次執行該方法
    '$route': 'fetchData'
  },

在導航完成前獲取數據:

beforeRouteEnter 守衛中獲取數據,當數據獲取成功後只調用 next 方法。
beforeRouteEnter (to, from, next) {
    getPost(to.params.id, (err, post) => {
        next(vm => vm.setData(err, post))
    })
},

// 路由改變前,組件就已經渲染完了
  // 邏輯稍稍不一樣
  beforeRouteUpdate (to, from, next) {
    this.post = null
    getPost(to.params.id, (err, post) => {
      this.setData(err, post)
      next()
    })
  },
  methods: {
    setData (err, post) {
      if (err) {
        this.error = err.toString()
      } else {
        this.post = post
      }
    }
  }

路由懶加載

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
相關文章
相關標籤/搜索