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://www.cnblogs.com/xxm980617/p/10668719.html

时间: 2024-10-09 10:07:32

Vue(基础八)_导航守卫(组件内的守卫)的相关文章

vue基础内容{通信,注册,路由,组件}

ES6常用语法 -- 变量 -- var 变量提升 -- let  {} -- const 常量 -- 模板字符串 -- `` -- ${} -- 函数 -- 箭头函数 -- this -- 普通函数取决于函数最近的调用者 -- 箭头函数取决于当前上下文环境 -- 数据的解构 -- 注意语法 -- 类 -- class 定义类 -- extends 继承 -- constructor 构造方法 -- 子类是没有this的 用super() -- export import -- export {

vue基础八

表单控件绑定 1.基础用法 你可以用 v-model 指令在表单控件元素上创建双向数据绑定.尽管有些神奇,但 v-model 本质上不过是语法糖,它负责监听用户的输入事件以更新数据,并特别处理一些极端的例子. 1.1文本 <input v-model="message" placeholder="edit me"> <p>Message is: {{ message }}</p> 1.2复选框 单个勾选框,逻辑值: <inp

Vue配置路由和传参方式及路由守卫!

安装路由 npm i vue-router -S 引入路由 import VueRouter form VueRouter 注入路由模块 Vue.use(VueRouter) 定义路由匹配规则 let routes = [ {...}, {...} ] 上列匹配规则中 对象有如下属性 path : 路由路径 component : 所加载的组件 name : 别名 redirect : 重定向 children : 子级路由 创建路由实例 let router = new VueRouter({

路由独享-组件内守卫

路由独享写法: import VueRouter from 'vue-router' Vue.use(VueRoter) const router = new VueRouter({ routes:[ {path:component:,name:,beforeEnter:((to,next,from)=>{ alert('路由独享-组件内守卫') next()//跳转 next(false)//不显示此路由下的组件 })} ], mode:'history', }) 组件内守卫:在组件内写 ex

Vue基础篇--8组件基础 component

Vue基础篇--8组件基础 component 1.简单示例 <div id='components1'> <button-conter></button-conter> </div> <script> // 定义一个名为button-conter组件 Vue.component("button-conter",{ data:function () { return { count:0 } }, template:`<b

vue自定义事件将组件内的数据传输到实例中去使用

vue自定义事件将组件内的数据传输到实例中去使用 <body> <div id="app"> <h1 style="color:deeppink">{{ outer_title }}</h1> //③给实例绑定一个方法 <hello :reader="new_msg"  v-on:chang_event="chang_tit"></hello> </

vue基础二,组件

vue二: 指令: 1,v-once指令: v-once:单独使用,限制的标签内容一旦赋值,便不可被动更改(如果是输入框,可以主动修改) <div id="app"> <input type="text" v-model="msg"> <!-- 一旦赋值,只可主动更改 --> <input type="text" v-model="msg" v-once> &

千锋教育Vue组件--vue基础的方法

课程地址: https://ke.qq.com/course/251029#term_id=100295989 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>vue基础的方法</title&

vue基础----组件通信(props,$emit,$attrs,$listeners)

一.父传子,子传孙 1. props 1>在父组件中通过子组件自定义的标签属性来传递数据. 2>在子组件中通过props声明希望用到的数据 1 <body> 2 <div id="app"> 3 <my-father :msg1="msg" a="10" :b="20" @click="fn"></my-father> 4 </div>