導航欄上有首頁、智能題庫、登陸、退出四個按鈕。javascript
用戶訪問首頁時,看到是首頁的內容html
1.當用戶訪問智能題庫時,此時要檢測用戶是否有權限訪問該智能題庫內容
若是沒有:檢測用戶是否登陸,若是沒有登陸則跳轉到登陸頁面。
登陸完成後,在localStorage中存儲該用戶的用戶名和密碼,而且馬上跳轉到智能題庫頁面vue
2.當用戶點擊退出,該用戶登陸直接刪除。java
<body> <div id="app"></div> <script type="text/javascript" src="vue.js"></script> <!--1.引入vue-router的對象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!--全局的VueRouter對象 vue-router還提供了兩個全局的組件router-link / router-view--> <script type="text/javascript"> // 2.讓Vue使用該VueRouter建立 Vue.use(VueRouter); var Home = { template:` <div> 我是首頁 </div> ` }; var Questionbank = { template:` <div> 我是題庫 </div> ` }; // 登陸組件 var Login = { data(){ // 數據聲明 return { name:'', pwd:'' } }, template:` <div> <input type="text" v-model="name"/> <input type="text" v-model="pwd"/> <input type="button" value="登陸" @click="loginHandler"/> </div> `, methods:{ loginHandler(){ // 要登陸了 alert(1); } } }; // 3.建立一個路由對象 var router = new VueRouter({ // 配置路由對象 routes:[ // 動態路由參數以冒號開頭 { path:'/home', component:Home, }, { path:'/questionbank', name:'questionbank', component:Questionbank, }, { path:'/login', name:'login', component:Login } ] }); var App = { // keep-alive組件保持緩存,把router-view渲染的出口緩存起來 template:` <div> <router-link to="/home">首頁</router-link> <router-link to="/questionbank">智能題庫</router-link> <router-link to="/login">登陸</router-link> <a href="javascript:void(0)" @click="clear">退出</a> <keep-alive> <router-view></router-view> </keep-alive> </div> `, methods:{ clear(){ // 退出 alert(1); } } }; new Vue({ el:'#app', components:{ App }, router, // router:router, 在key和value相同時能夠只寫一個 template:`<App/>` }); </script> </body>
基本的頁面框架已經搭好,後面但願作到是:在點擊智能題庫時,判斷是否登陸,沒有登陸的話跳轉到登陸頁面登陸,登陸成功後,跳轉回智能題庫頁面顯示。node
定義路由的時候能夠配置 meta 字段。git
routes
配置中的每一個路由對象爲 路由記錄。路由記錄能夠是嵌套的,所以,當一個路由匹配成功後,他可能匹配多個路由記錄。github
一個路由匹配到的全部路由記錄會暴露爲 $route
對象 (還有在導航守衛中的路由對象) 的 $route.matched
數組。所以,咱們須要遍歷 $route.matched
來檢查路由記錄中的 meta
字段。vue-router
// 3.建立一個路由對象 var router = new VueRouter({ // 配置路由對象 routes:[ // 動態路由參數以冒號開頭 { path:'/home', component:Home, }, { path:'/questionbank', name:'questionbank', component:Questionbank, // 給將來的路由作權限控制 meta:{ // 若是meta對象的auth爲true,代表訪問該組件時須要登陸 auth:true } }, { path:'/login', name:'login', component:Login } ] });
必定要調用next,若是不調用next,那麼頁面會卡住,路由就再也不走了。編程
// 全局的導航守衛(對路由的切換進行守衛) router.beforeEach(function (to, from, next) { console.log(to); console.log(from); // 必定要調用next,若是不調用next,那麼頁面會卡住,路由再也不走了 if(to.meta.auth){ // 用戶點擊了智能題庫的導航,該用戶未登陸,須要登陸判斷 if (localStorage.getItem('user')){ // 用戶登陸了,不爲空,放行 next(); }else{ // 爲空進入登陸頁面 next({path:'/login'}); } }else { // 沒有點擊智能題庫,直接放行 next(); } });
// 登陸組件 var Login = { data(){ // 數據聲明 return { name:'', pwd:'' } }, template:` <div> <input type="text" v-model="name"/> <input type="text" v-model="pwd"/> <input type="button" value="登陸" @click="loginHandler"/> </div> `, methods:{ loginHandler(){ // 要登陸了 // 存儲用戶名和密碼,保存到localStorage,而後跳轉到相應的路由(智能導航) localStorage.setItem('user', {name:this.name, pwd:this.pwd}) // 編程式導航 this.$router.push({name:'questionbank'}); } } };
var App = { // keep-alive組件保持緩存,把router-view渲染的出口緩存起來 template:` <div> <router-link to="/home">首頁</router-link> <router-link to="/questionbank">智能題庫</router-link> <router-link to="/login">登陸</router-link> <a href="javascript:void(0)" @click="clear">退出</a> <keep-alive> <router-view></router-view> </keep-alive> </div> `, methods:{ clear(){ // 退出 localStorage.removeItem('user'); // 清除保存的用戶 this.$router.push('/login'); // 跳轉到登陸頁面 } } };
項目源碼查看api
(1)訪問頁面後,點擊智能題庫
(2)填寫登陸信息登陸
(3)點擊登陸後頁面跳轉
(4)點擊退出
vue-router
提供的導航守衛主要用來經過跳轉或取消的方式守衛導航。
導航守衛就是路由跳轉過程當中的一些鉤子函數,再直白點路由跳轉是一個大的過程,這個大的過程分爲跳轉前中後等等細小的過程,在每個過程當中都有一函數,這個函數能讓你操做一些其餘的事兒的時機,這就是導航守衛。
所以有多種機會植入路由導航過程當中(導航守衛分類):全局的、單個路由獨享的、組件級的。
1.全局前置守衛:beforeEach
2.路由beforeEnter守衛
3.組件路由守衛beforeRouteEnter,此時this並不指向該組件實例
4.全局解析守衛:beforeResolve
5.全局後置守衛:afterEach
6.組件生命週期:beforeCreate
7.組件生命週期:created
8.組件生命週期:beforeMount
9.組件生命週期:mounted
10.組件路由守衛beforeRouteEnter的next回調
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()
註冊過的回調。
全局路由守衛指路由實例上直接操做的鉤子函數,他的特色是全部路由配置的組件都會觸發,直白點就是觸發路由就會觸發這些鉤子函數,以下的寫法。鉤子函數按執行順序包括beforeEach、beforeResolve(2.5+)、afterEach三個。
在路由跳轉前觸發,參數包括to,from,next三個,這個鉤子主要用於登陸驗證,也就是路由還沒跳轉提早告知,以避免跳轉了再通知就爲時已晚。
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
當一個導航觸發時,全局前置守衛按照建立順序調用。守衛是異步解析執行,此時導航在全部守衛 resolve 完以前一直處於 等待中。
和beforeEach相似,也是路由跳轉前觸發,參數也是to,from,next三個。
區別在於:導航被確認以前,同時在全部組件內守衛和異步路由組件被解析以後,解析守衛就被調用。
和beforeEach相反,他是在路由跳轉完成後觸發,參數包括to,from沒有了next,這些鉤子不會接受 next
函數也不會改變導航自己。
router.afterEach((to, from) => { // ... })
指在單個路由配置的時候也能夠設置的鉤子函數,其位置就是下面示例中的位置,也就是像Foo這樣的組件都存在這樣的鉤子函數。
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
這些守衛與全局前置守衛的方法參數是一致的。
指在組件內執行的鉤子函數,相似於組件內的生命週期,至關於爲配置路由的組件添加的生命週期鉤子函數。鉤子函數按執行順序包括beforeRouteEnter、beforeRouteUpdate (2.2+)、beforeRouteLeave三個,執行位置以下:
<template> ... </template> export default{ data(){ //... }, 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
傳遞迴調的惟一守衛。對於 beforeRouteUpdate
和 beforeRouteLeave
來講,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) } }
beforeEach
守衛。beforeRouteUpdate
守衛 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守衛 (2.5+)。afterEach
鉤子。beforeRouteEnter
守衛中傳給 next
的回調函數。