Vue(基礎八)_導航守衛(組件內的守衛)


一、前言                                                                                            

主要通過一個例子演示三個鈎子的作用:

                                                                   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>
beforeRouteEnter

(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>
beforeRouteUpdate

(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>
beforeRouteLeave

 

 

 

 

三、總結                                                                                            

beforeRouteEnter:用於組件創建之前,公共組件不起作用

beforeRouteUpdate:用於公共組件的情況

 參考文章:https://juejin.im/post/5b41bdef6fb9a04fe63765f1#heading-17


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM