vue路由:html
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;
例如從/user/foo導航到/user/bar,原來的組件會被複用, 這種方式獲取url上的參數能夠watch來監視$route對象來獲取
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.push
或 router.replace
中提供 onComplete
和 onAbort
回調做爲第二個和第三個參數。這些回調將會在導航成功完成 (在全部的異步鉤子被解析以後) 或終止 (導航到相同的路由、或在當前導航完成以前導航到另外一個不一樣的路由) 的時候進行相應的調用。瀏覽器
注意: 若是目的地和當前路由相同,只有參數發生了改變 (好比從一個用戶資料到另外一個 /users/1
-> /users/2
),你須要使用 beforeRouteUpdate
來響應這個變化 (好比抓取用戶信息)。異步
router.go(n):this.$router.go(-1)後退1步 this.$router.go(1)前進1步 .....等價於window.history.go(n)。
命名路由即在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) => { // ... } } ] })
beforeEach
守衛。beforeRouteUpdate
守衛 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守衛 (2.5+)。afterEach
鉤子。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() } })
<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 } ] })