一、前言
主要通過一個例子演示三個鈎子的作用:
1、beforeRouteEnter()
2、beforeRouteUpdate()
3、beforeRouteLeave
二、主要內容
1、舉例說明:下面有三個組件,用戶1,用戶2公用一個公共組件。
2、beforeRouteEnter()
(1)詳細說明beforeRouteEnter
//在路由改變之前 beforeRouteEnter (to, from, next){ //在渲染該組件的對應路由被confirm前調用 //不能獲取當前組件實例this,因為在守衛執行之前,實例還沒有被創建 //但是你可以通過傳一個回調函數給next來訪問組件實例。在導航被確認的時候進行回調,並且把組件實例作為回調方法的參數 } /* */
(2)實現beforeRouteEnter的代碼以及演示:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"></div> <script src="vue.js"></script> <script type="text/javascript" src="vue-router.js"></script> <script type="text/javascript" src="axios.js"></script> <script type="text/javascript"> Vue.use(VueRouter) //用戶組件 var User = { data(){ return{ user:'', error:null, timer:null, num:0, msg:'',//輸入框中輸入的內容 msg1:'',//頁面中展示的數據 confirm:true } }, template:`<div> <div>{{num}}</div> <input type="text" v-model='msg'/> <p>{{msg1}}</p> <button>保存</button> <div v-if="error" class = 'error'>{{error}}</div> <div class='user' v-if='user'> {{user}} </div> </div>`, methods:{ setDatas(user){ this.user = user; }, setError(err){ this.error=err; } }, beforeRouteEnter(to,from,next){ //在渲染該組件的對應路由被confirm前調用 //不能獲取組件實例this //因為當守衛執行前,組件還沒創建,也就是路由切換之前 //但是你可以通過傳一個回調給next來訪問組件實例。在導航被確認的時候執行回調,並將組件實例作為回調方法的參數 //全局的axios調用 console.log(to); axios.get(`http://127.0.0.1:8888/user/${to.params.id}`) .then(res=>{ next(vm=>vm.setDatas(res.data)); }) .catch(err=>{ next(vm => vm.setError(err)) }) } } //測試組件 var Test = { template:`<div>我是測試組件</div>` } //路由配置 var router = new VueRouter({ routes:[{ path:'/user/:id', name:'user', component:User },{ path:'/test', name:'test', component:Test }] }) //入口組件 var App = { template:`<div> <router-link :to='{name: "test"}'>測試</router-link> <router-link :to='{name:"user",params:{id:1}}'>用戶1</router-link> <router-link :to='{name:"user",params:{id:2}}'>用戶2</router-link> <router-view></router-view> </div>` } //創建vue實例 new Vue({ el:'#app', data:{ }, components:{ App }, template:'<App/>', router }) </script> </body> </html>
(3)具體實現
(4)測試:當從“測試”組件進入到用戶組件的時候,發現組件中的內容發生改變,但是當從用戶1切換到用戶2的時候,發現沒反應,因為用戶1和用戶2公用的公共組件user,
“用戶1”切換到“用戶2”的時候沒有組件的創建和銷毀
2、beforeRouteUpdate()
(1)在組件內部可以用beforeRouteUpdate來解決上面出現的問題
//路由更新時 beforeRouteUpdate(to, from, next) { //在當前路由改變,但是該組件被復用時調用 //舉例來說:對於一個帶有動態參數的路徑 /foo/:id, 在/foo/1 和 /foo/2 之間跳轉的時候,由於會渲染同樣的foo組件, 因此組件實例會被重復利用。 此時這個鈎子就可以在這個時候調用 //在這里可以獲取到當前的this }
(2)beforeRouteUpdate的代碼如下

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"></div> <script src="vue.js"></script> <script type="text/javascript" src="vue-router.js"></script> <script type="text/javascript" src="axios.js"></script> <script type="text/javascript"> Vue.use(VueRouter) //用戶組件 var User = { data(){ return{ user:'', error:null, timer:null, num:0, msg:'',//輸入框中輸入的內容 msg1:'',//頁面中展示的數據 confirm:true } }, template:`<div> <div>{{num}}</div> <input type="text" v-model='msg'/> <p>{{msg1}}</p> <button>保存</button> <div v-if="error" class = 'error'>{{error}}</div> <div class='user' v-if='user'> {{user}} </div> </div>`, methods:{ setDatas(user){ this.user = user; }, setError(err){ this.error=err; } }, beforeRouteEnter(to,from,next){ //在渲染該組件的對應路由被confirm前調用 //不能獲取組件實例this //因為當守衛執行前,組件還沒創建,也就是路由切換之前 //但是你可以通過傳一個回調給next來訪問組件實例。在導航被確認的時候執行回調,並將組件實例作為回調方法的參數 //全局的axios調用 console.log(to); axios.get(`http://127.0.0.1:8888/user/${to.params.id}`) .then(res=>{ next(vm=>vm.setDatas(res.data)); }) .catch(err=>{ next(vm => vm.setError(err)) }) }, beforeRouteUpdate(to, from, next){ this.$axios.get(`http://127.0.0.1:8888/user/${to.params.id}`). then(res=>{ this.setDatas(res.data); next(); //一定要用next,不然會被卡主 }) .catch(err=>{ this.setError(err); next(); }) } } //測試組件 var Test = { template:`<div>我是測試組件</div>` } //路由配置 var router = new VueRouter({ routes:[{ path:'/user/:id', name:'user', component:User },{ path:'/test', name:'test', component:Test }] }) Vue.prototype.$axios = axios //入口組件 var App = { template:`<div> <router-link :to='{name: "test"}'>測試</router-link> <router-link :to='{name:"user",params:{id:1}}'>用戶1</router-link> <router-link :to='{name:"user",params:{id:2}}'>用戶2</router-link> <router-view></router-view> </div>` } //創建vue實例 new Vue({ el:'#app', data:{ }, components:{ App }, template:'<App/>', router }) </script> </body> </html>
(3)測試:發現公共組件部分,可以通過切換路由,渲染出各自的數據了
3、beforeRouteLeave
(1)beforeRouteLeave()
beforeRouteLeave(to, from, next){ //離開當前組件時調用 }
(2)可以利用這個方法當用戶離開某個頁面的時候,提示用戶保存信息
比如在寫博客是點擊其他頁面時,會提示是否保存當前內容
(3)具體代碼

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"></div> <script src="vue.js"></script> <script type="text/javascript" src="vue-router.js"></script> <script type="text/javascript" src="axios.js"></script> <script type="text/javascript"> Vue.use(VueRouter) //用戶組件 var User = { data(){ return{ user:'', error:null, timer:null, num:0, msg:'',//輸入框中輸入的內容 msg1:'',//頁面中展示的數據 confirm:true } }, template:`<div> <div>{{num}}</div> <input type="text" v-model='msg'/> <p>{{msg1}}</p> <button @click="save">保存</button> <div v-if="error" class = 'error'>{{error}}</div> <div class='user' v-if='user'> {{user}} </div> </div>`, methods:{ setDatas(user){ this.user = user; }, setError(err){ this.error=err; }, save(){ this.msg1 = this.msg; this.msg = ''; this.confirm = true; } }, beforeRouteEnter(to,from,next){ //在渲染該組件的對應路由被confirm前調用 //不能獲取組件實例this //因為當守衛執行前,組件還沒創建,也就是路由切換之前 //但是你可以通過傳一個回調給next來訪問組件實例。在導航被確認的時候執行回調,並將組件實例作為回調方法的參數 //全局的axios調用 console.log(to); axios.get(`http://127.0.0.1:8888/user/${to.params.id}`) .then(res=>{ next(vm=>vm.setDatas(res.data)); }) .catch(err=>{ next(vm => vm.setError(err)) }) }, beforeRouteUpdate(to, from, next){ //當前路由改變,但是組件被復用(也就是公共組件) this.$axios.get(`http://127.0.0.1:8888/user/${to.params.id}`). then(res=>{ this.setDatas(res.data); next(); //一定要用next,不然會被卡主 }) .catch(err=>{ this.setError(err); next(); }) }, beforeRouteLeave(to, from, next){ //導航離開該組件的對應路由時調用 if (this.confirm == true && this.msg) { //證明用戶輸入了內容 需要提示用戶 保存重要信息 this.confirm= confirm('請保存重要信息'); //用戶點擊了取消按鈕 返回值為false next(false); }else if(this.confirm == false){ alert('請保存信息后退出'); next(false); }else{ next();//放行路由 } } } //測試組件 var Test = { template:`<div>我是測試組件</div>` } //路由配置 var router = new VueRouter({ routes:[{ path:'/user/:id', name:'user', component:User },{ path:'/test', name:'test', component:Test }] }) Vue.prototype.$axios = axios //入口組件 var App = { template:`<div> <router-link :to='{name: "test"}'>測試</router-link> <router-link :to='{name:"user",params:{id:1}}'>用戶1</router-link> <router-link :to='{name:"user",params:{id:2}}'>用戶2</router-link> <router-view></router-view> </div>` } //創建vue實例 new Vue({ el:'#app', data:{ }, components:{ App }, template:'<App/>', router }) </script> </body> </html>
三、總結
beforeRouteEnter:用於組件創建之前,公共組件不起作用
beforeRouteUpdate:用於公共組件的情況
參考文章:https://juejin.im/post/5b41bdef6fb9a04fe63765f1#heading-17