zoukankan      html  css  js  c++  java
  • 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

    虽然现在走得很慢,但不会一直这么慢
  • 相关阅读:
    Apache Kafka:下一代分布式消息系统
    深入理解Java之线程池
    JAVA中线程同步的方法(7种)汇总
    String、StringBuffer与StringBuilder之间区别
    Java中是否可以继承String类,为什么
    JAVA4种线程池的使用
    一分钟教你知道乐观锁和悲观锁的区别
    java常见面试题及答案 11-20(JVM)
    springmvc中的页面解析器ViewResolver不起作用,变量输出字符串的解决方案
    SpringMVC默认欢迎页面的问题
  • 原文地址:https://www.cnblogs.com/xxm980617/p/10668719.html
Copyright © 2011-2022 走看看