zoukankan      html  css  js  c++  java
  • 八、vue基础-router基础、动态参数、组件复用、配置404、嵌套路由、编程式导航、命名视图、重定向、导航守卫

    1.基本使用
      a.创建一个VueRouter对象:new VueRouter()
      b.在VueRouter中,需要传递一个routes参数,这个参数是一个数组类型,数据中存储的是对象,对象中最少有两个属性,一个是path代表的是url,一个是component代表数据更新的组件,代码如下:

    let router = new VueRouter({
                    routes:[
                    {path:"/",component:index},
                    {path:"/find",component:find},
                    {path:"/friend",component:friend}
                    ]

      .将router传给Vue
      d.把网页中之前的a标签替换成router-link标签
      e.使用router-view指定网页中那个地方要被更新。 全部代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src="vue-router.js"></script>
                <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
                <title>vue-router练习</title>
            </head>
            <body>
                <div id='app'>
                    <nav class="navbar navbar-default">
                        <div class="container-fluid">
                        <!-- Brand and toggle get grouped for better mobile display -->
                        <div class="navbar-header">
                            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                            <span class="sr-only">Toggle navigation</span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            </button>
                            <router-link to="/" class="navbar-brand">我的音乐</router-link>
                        </div>
                        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                            <ul class="nav navbar-nav">
                            <li class="active">
                                <router-link to="/">首页</router-link>
                            </li>
                            <li>
                                <router-link to="/find">发现音乐</router-link>
                            </li>
                            <li>
                                <router-link to="/friend">我的朋友</router-link>
                            </li>
                            </ul>
                        </div><!-- /.navbar-collapse -->
                        </div><!-- /.container-fluid -->
                    </nav> 
                    <div class="container">
                        <router-view></router-view>
                    </div>
                </div>
                <script>
                var index = Vue.extend({template:"<h1>首页</h1>"})
                var find = Vue.extend({template:"<h1>发现音乐</h1>"})
                var friend = Vue.extend({template:"<h1>我的朋友</h1>"})
                let router = new VueRouter({
                    routes:[
                    {path:"/",component:index},
                    {path:"/find",component:find},
                    {path:"/friend",component:friend}
                    ]
                })
                    new Vue({
                        el:'#app',
                        // router:router
                        router
                    })
                </script>
            </body>
            </html>

    2.动态路由
      1.在url中,通过定义一个参数那么以后url中就可以动态的传递这个参数,语法是:/profile/:参数名
      2.在组件中可以通过this.$route.params.参数名拿到,或者是组件中的模块中,可以通过$route.params.参数名拿到
      3.this.$route和this.$router的区别:
        a.this.$route:代表是当前这个路由的信息集合
        b.this.$router:代表是全局的VueRouter对象
    代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src="vue-router.js"></script>
                <title>动态参数</title>
            </head>
            <body>
                <div id='app'>
                    <ul>
                        <li>
                            <router-link to="/">首页</router-link>
                        </li>
                        <li>
                            <router-link to="profile/123">个人中心</router-link>
                        </li>
                    </ul>
                    <router-view></router-view>
                </div>
                <script>
                    let index = Vue.extend({template:"<h1>首页来了</h1>"})
                    let profile = Vue.extend({template:"<h1>个人中心来了:{{$route.params.userid}}</h1>"})
    
                    let router =  new VueRouter({
                        routes:[
                            {path:"/",component:index},
                            {path:"/profile/:userid",component:profile},
                        ]
                    })
                    new Vue({
                        el:'#app',
                        router
                    })
                </script>
            </body>
            </html>

    3.组件复用:当使用路由参数时,原来组件的实力会被复用,意味着组件的生命周期钩子不会再被调用。有两种方法解决:
      a.监听this.$router属性,通过判断to和from来更新数据
      b.使用导航守卫的beforeRouteUpdate方法们也可以获取to和from,但是要记得调用next(),否则页面不会更新

    <!DOCTYPE html>
        <html lang='en'>
        <head>
            <meta charset='UTF-8'>
            <meta name='viewport' content='width=device-width, initial-scale=1.0'>
            <meta http-equiv='X-UA-Compatible' content='ie=edge'>
            <script src='vue.js'></script>
            <script src="vue-router.js"></script>
            <title>组件复用</title>
        </head>
        <body>
            <div id='app'>
                <ul>
                    <li>
                        <router-link to="/profile/张三">张三的个人中心</router-link>
                    </li>
                    <li>
                        <router-link to="/profile/李四">李四的个人中心</router-link>
                    </li>
                </ul>
                <router-view></router-view>
            </div>
            <script>
                let index = Vue.extend({
                    template:"<h1>首页来了</h1>"
                })
                let profile = Vue.extend({
                    template:"<h1>个人中心来了:{{$route.params.userid}}</h1>",
                    mounted(){
                        console.log(this.$route.params.userid);
                    },
                    // watch:{
                    //     "$route": function(to,from){
                    //         console.log("to:",to);
                    //         console.log("from:",from);
                    //         console.log('看看执行么有');
                    //     }
                    beforeRouteUpdate: function(to,from,next){
                        console.log("to:",to);
                        console.log("from:",from);
                        next()  
                    }
                })
    
                let router =  new VueRouter({
                    routes:[
                        {path:"/",component:index},
                        {path:"/profile/:userid",component:profile},
                    ]
                })
                new Vue({
                    el:'#app',
                    router
                })
            </script>
        </body>
        </html>  

    4.404配置:
      a.前端页面配置:子啊所有路由后面增加一个*的url,让这个url映射到一个404的组件
      b.数据不存在的处理:通过访问服务器来判断,可以通过 this.$router.replace("/404"),跳转到404页面
    代码如下:

    <!DOCTYPE html>
        <html lang='en'>
        <head>
            <meta charset='UTF-8'>
            <meta name='viewport' content='width=device-width, initial-scale=1.0'>
            <meta http-equiv='X-UA-Compatible' content='ie=edge'>
            <script src='vue.js'></script>
            <script src="vue-router.js"></script>
            <title>404配置</title>
        </head>
        <body>
            <div id='app'>
                <router-view></router-view>
            </div>
            <script>
                let index = Vue.extend({
                    template:"<h1>首页</h1>"
                })
                let aboutus = Vue.extend({
                    template:"<p>关于我们</p>"
                })
                let profile = Vue.extend({
                    template:"<p>个人中心:{{$route.params.userid}}</p>",
                    mounted(){
                        if(this.$route.params.userid !='123'){
                            this.$router.replace("/404")
                        }
                    },
                })
                let notfound = Vue.extend({
                    template:"<p>404页面没有找到</p>"
                })
                let router = new VueRouter({
                    routes:[
                        {path:"/",component:index},
                        {path:"/aboutus",component:aboutus},
                        {path:"/profile/:userid",component:profile},
                        {path:"/404",component:notfound},
                        {path:"*",component:notfound},
                    ]
                })
                new Vue({
                    el:'#app',
                    router:router
                })
            </script>
        </body>
        </html>

    5.路由嵌套(子路由)
      a.在大的路由下面,需要子路由切换数据的时候,可以使用路由嵌套
      b.定义路由的时候,不需要在routes中单独添加映射,而应该放在父路由的childern中
      c.在父路由的组件中,要谈价路由出口
    代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src='vue-router.js'></script>
                <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
                <title>嵌套路由</title>
            </head>
            <body>
                <div id='app'>
                    <nav class="navbar navbar-default">
                        <div class="container">
                            <div class="navbar-header">
                                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                                    <span class="sr-only">哈哈</span>
                                    <span class="icon-bar"></span>
                                    <span class="icon-bar"></span>
                                    <span class="icon-bar"></span>
                                </button>
                                <a class="navbar-brand" href="#">学习</a>
                            </div>
                            <div class="collapse navbar-collapse" id="bs-example-navber-collapse-1">
                                <ul class="nav navbar-nav">
                                    <li class ="active">
                                        <router-link to="/">首页</router-link>
                                    </li>
                                    <li>
                                        <router-link to="/user/123">我的主页</router-link>
                                    </li>
                                </ul>
                            </div>
                        </div>
                    </nav>
                    <div class="container">
                        <router-view></router-view>
                    </div>
                </div>
                <script>
                    let index=Vue.extend({
                        template:"<h1>首页</h1>"
                    })
                    let user=Vue.extend({
                        template:`
                        <div>
                            <h1>我的主页</h1>
                            <ul class="nav nav-tabs">
                                <li role="presentation" class="active">
                                    <router-link to="/user/123/users">设置</router-link>
                                </li>
                                <li role="presentation">
                                    <router-link to="/user/123/xiaoxi">消息</router-link>
                                </li>
                            </ul>
                            <div class="container">
                                <router-view></router-view>
                            </div>
                        </div> 
                        `
                    })
                    let users=Vue.extend({
                        template:"<h3>个人中心</h3>"
                    })
                    let xiaoxi=Vue.extend({
                        template:"<h3>个人消息</h3>"
                    })
                    let router=new VueRouter({
                        routes:[
                            {path:"/",component:index},
                            {
                                path:"/user/:userid",
                                component:user,
                                children:[
                                    {path:"",component:users},
                                    {path:"users",component:users},
                                    {path:"xiaoxi",component:xiaoxi},
                                ]
                            },
                        ]
                    })
                    new Vue({
                        el:'#app',
                        router
                    })
                </script>
            </body>
            </html>

    6.编程试导航
      a. this.$router.puth:转到下一个url,会把新转入的url添加到浏览器的history中,push的参数:
      字符串:直接就是路径
      对象:path和name都可以,但是如果是使用了path,参数要放在path,放在params中没有效果
      b. this.$router.replace:用法和push是一样的,区别是替换当前页面
      c. this.$router.go:往前、往后
    代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src='vue-router.js'></script>
                <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
                <title>嵌套路由</title>
            </head>
            <body>
                <div id='app'>
                    <button @click="gotoPost">跳到帖子列表</button>
                    <button @click="gotoProfile">跳到个人中心</button>
                    <button @click="gotoLogin">登录</button>
                    <button @click="gotoNext">下一步</button>
                    <button @click="gotoUp">上一步</button>
                    <router-view></router-view>
                </div>
                <script>
                    let post=Vue.extend({
                        template:"<h1>帖子列表</h1>"
                    })
                    let profile=Vue.extend({
                        template:"<h3>个人中心:{{$route.params.userid}}</h3>"
                    })
                    let login=Vue.extend({
                        template:"<h3>登录界面,打印$route.query{{$route.query}},打印$route.params{{$route.params}},打印$route.fullPath{{$route.fullPath}}</h3>"
                    })
                    let router=new VueRouter({
                        routes:[
                            {path:"/post",component:post},
                            {path:"/profile/:userid",component:profile,name:"myprofile"},
                            {path:"/login",component:login},
                        ]
                    })
                    new Vue({
                        el:'#app',
                        router:router,
                        methods:{
                            gotoPost(){
                            this.$router.push("/post")
                            },
                            gotoProfile(){
                                // this.$router.push("/profile/123")
                                // this.$router.push({path:"/profile/123"})
                                // this.$router.push({name:"myprofile",params:{userid:"222"}})
                                this.$router.replace({name:"myprofile",params:{userid:"222"}})
                            },
                            gotoLogin(){
                                let currentPath = this.$route.fullPath
                                this.$router.push({path:"/login",query:{from:currentPath}})
                            },
                            gotoNext(){
                                this.$router.go(1)
                            },
                            gotoUp(){
                                this.$router.go(-1)
                            }           
                        }
                    })
                </script>
            </body>
            </html>

    7.命名视图
      a.路由名称:可以在定义路由的时候指定name,使用的时候们可以直接传递name值就可以了
      b.命名视图(多组件):在一个页面中,可以通过命名视图展示多个组件,有一下步骤:
        (1)在定义路由的时候们需要传递components,然后把所有需要展示的路由都放到这个里面,components是一个对象,{name:组件}的映射。
        (2)在模板中,就是通过 <router-view name="组件名"></router-view>来实现
    代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src='vue-router.js'></script>
                <title>命名视图</title>
                
                <style>
                    .header{
                        width: 100%;
                        height: 80px;
                        background: cadetblue;
                    }
                    .body{
                        display: flex;
                        height: 500px;
                    }
                    .body .sidebar{
                        width: 200px;
                        background: darkgrey;
                    }
                    .body .main{
                        flex: 1;
                        background: cyan;
                    }   
                    .footer{
                        height: 100px;
                        background: darksalmon;
                    }
                    
                </style>
            </head>
            <body>
                <div id='app'>
                    <div class="header">
                        <router-view name="header"></router-view>
                    </div>
                    <div class="body">
                        <div class="sidebar">
                            <router-view name="sidebar"></router-view>
                        </div>
                        <div class="main">
                            <router-view name="main"></router-view>
                        </div>
                    </div>
                    <div class="footer">
                        <router-view name="footer"></router-view>
                    </div>
                </div>
                <script>
                    let header = Vue.extend({
                        template:"<div>这个是header部分</div>"
                    })
                    let sidebar = Vue.extend({
                        template:"<div>这个是sidebar部分</div>"
                    })
                    let main = Vue.extend({
                        template:"<div>这个是main部分</div>"
                    })
                    let footer = Vue.extend({
                        template:"<div>这个是footer部分</div>"
                    })
                    let router = new VueRouter({
                        routes:[
                            {path:"/",components:{
                                header:header,
                                sidebar:sidebar,
                                main:main,
                                footer:footer
                            }}
                        ]
                    })
                    new Vue({
                        el:'#app',
                        router
                    })
                </script>
            </body>
            </html>

    8.重定向和别名:
      a.重定向:在定义路由的时候,可以加一个redirect参数,用来重定向到另外一个页面。
      b.别名:在定义的时候,可以加一个alias参数,用来标识这个url的别名,之后可以通过别名可以访问到这个页面。

    <!DOCTYPE html>
        <html lang='en'>
        <head>
            <meta charset='UTF-8'>
            <meta name='viewport' content='width=device-width, initial-scale=1.0'>
            <meta http-equiv='X-UA-Compatible' content='ie=edge'>
            <script src='vue.js'></script>
            <script src='vue-router.js'></script>
            <title>重定向和别名</title>
        </head>
        <body>
            <div id='app'>
                <router-view></router-view>
            </div>
            <script>
                let index = {template:"<h1>首页</h1>"}
                let login = {template:"<h1>登录</h1>"}
                let router = new VueRouter({
                    routes:[
                        {path:"/",redirect:'/login'},
                        {path:"/login",component:login,alias:"/test"}
                    ]
                })
                new Vue({
                    el:'#app',
                    router
                })
            </script>
        </body>
        </html>

    9.导航守卫-全局导航守卫:在VueRouter上实现的,有两个函数,beforeEach、afterEach
      1.beforeEach(to,from,next) to:代表上一个路由。from:代表下一个路由对象。next:代表是控制下一步路由怎么走
      next()按照正常的流程来
      next("/")就会把之前的路由断掉,走到首页中去
      next(false)或者没有调用next() 不会做任务跳转
      2.afterEach(to,from) 路由完成后回调
    代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src='vue-router.js'></script>
                <title>全局导航守卫</title>
            </head>
            <body>
                <div id='app'>
                    <router-link to="/">首页</router-link>
                    <router-link to="/account">我的账户</router-link>
                    <router-link to="/order">我的订单</router-link>
                    <router-link to="/login">登录界面</router-link>
                    <router-view></router-view>
                </div>
                <script>
                    // const logined=false
                    const logined=true
                    let index = {template:"<h1>首页</h1>"}
                    let account = {template:"<h1>我的账户</h1>"}
                    let order = {template:"<h1>我的订单</h1>"}
                    let login = {template:"<h1>登录界面</h1>"}
                    var router = new VueRouter({
                        routes:[
                            {path:"/",component:index,name:"index"},
                            {path:"/account",component:account,name:"account"},
                            {path:"/order",component:order,name:"order"},
                            {path:"/login",component:login,name:"login"}
                        ]
                    })
                    router.beforeEach(function(to,from,next){
                        //next()按照正常的流程来
                        //next("/")就会把之前的路由断掉,走到首页中去
                        //next(false)或者没有调用next() 不会做任务跳转
                        //请求需要授权的路由
                        const authRouters=['account','order']
                        //判断有没有下标
                        if(authRouters.indexOf(to.name)>=0){
                            //如果没有登录
                            console.log('name',to.name);
                            if(!logined){
                                next('/login')
                            }else{
                                next()
                            }
                        //如果是访问登录页面
                        }else if(to.name=='login'){
                            //如果登录了,到首页
                            if(logined){
                                next('/')
                            }else{
                                next()
                            }
                        }else{
                            next()
                        }
                    })
                    router.afterEach(function(to,from){
                        console.log('to',to);
                        console.log('from',from);
                    })
                    new Vue({
                        el:'#app',
                        router
                    })
                </script>
            </body>
            </html>


    10.导航守卫--路由导航守卫:beforeEnter:function(to,from,next)
    代码如下:

    <!DOCTYPE html>
                <html lang='en'>
                <head>
                    <meta charset='UTF-8'>
                    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                    <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                    <script src='vue.js'></script>
                    <script src='vue-router.js'></script>
                    <title>路由导航守卫</title>
                </head>
                <body>
                    <div id='app'>
                        <router-link to="/">首页</router-link>
                        <router-link to="/account">我的账户</router-link>
                        <router-link to="/order">我的订单</router-link>
                        <router-link to="/login">登录界面</router-link>
                        <router-view></router-view>
                    </div>
                    <script>
                        const logined=true
                        //const logined=false
                        let index = {template:"<h1>首页</h1>"}
                        let account = {template:"<h1>我的账户</h1>"}
                        let order = {template:"<h1>我的订单</h1>"}
                        let login = {template:"<h1>登录界面</h1>"}
                        var router = new VueRouter({
                            routes:[
                                {path:"/",component:index,name:"index"},
                                {path:"/account",component:account,name:"account"},
                                {path:"/order",component:order,name:"order"},
                                {path:"/login",component:login,name:"login",beforeEnter:function(to,from,next){
                                    if(logined){
                                        next("/")
                                    }else{
                                        next()
                                    }
                                }}
                            ]
                        })
    
                        new Vue({
                            el:'#app',
                            router
                        })
                    </script>
                </body>
                </html>

    11.导航路由--组件导航守卫:
      beforeRouteEnter:function(to,from,next):当前页面被进入之前调用
      beforeRouteUpdate:function(to,from,next):当前页面被复用,参数改变了会调用
      beforeRouteLeave(to,from,next):当前页面即将离开调用
    代码如下:

    <!DOCTYPE html>
            <html lang='en'>
            <head>
                <meta charset='UTF-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1.0'>
                <meta http-equiv='X-UA-Compatible' content='ie=edge'>
                <script src='vue.js'></script>
                <script src='vue-router.js'></script>
                <title>组件导航守卫</title>
            </head>
            <body>
                <div id='app'>
                    <router-link to="/">首页</router-link>
                    <router-link to="/account/111">111我的账户</router-link>
                    <router-link to="/account/222">222我的账户</router-link>
                    <router-view></router-view>
                </div>
                <script>
                    let index = {template:"<h1>首页</h1>"}
                    let account = {
                        data:function(){
                            return {
                                username:"zyb"
                            }
                        },
                        template:"<h1>我的账户</h1>",
                        beforeRouteEnter:function(to,from,next){
                        console.log('to',to),
                        console.log('from',from),
                        console.log(this.username),//访问不到
                        next(vm =>{
                            console.log("username:",vm.username);
                        })
                    },  beforeRouteUpdate:function(to,from,next){
                        console.log('to',to),
                        console.log('from',from),
                        next()
                    },
                        beforeRouteLeave(to,from,next){
                            let answer = window.confirm("要离开?")
                            if(answer){
                                next()
                            }
                        }
                    }
                    var router = new VueRouter({
                        routes:[
                            {path:"/",component:index,name:"index"},
                            {path:"/account/:userid",component:account,name:"account"},
                        ]
                    })
                    new Vue({
                        el:'#app',
                        router
                    })
                </script>
            </body>
            </html>

    *导航守卫执行的流程:
    1.导航被触发
    2.在失活的组件里调用离开守卫
    3.调用全局的berofeEach守卫
    4.在重用的组件里调用beforeRouteUpdate 守卫
    5.在路由配置李调用
    6.解析异步路由组件
    7.在被激活的组件里调用
    8.调用全局的beforeRouteLeave 守卫
    9.导航被确认
    10.调用全局的beforeEach 钩子
    11.触发 DOM更新
    12.用创建好的实例调用beforeRouteEnter 守卫中传给next 的回调函数

  • 相关阅读:
    AirtestIDE这个隐藏的小助手,还没用过你就亏啦!
    不懂抓包也能做APP爬虫?1招教你爬取抖音流行歌名
    巧用bat文件做Airtest脚本的“批量运行”
    AirtestIDE1.2.4、1.2.5新版来袭!新增自动更新、iOS更多版本支持...
    NodeService Ensure that Node.js is installed and can be found in one of the PATH directories
    NET CORE通过NodeService调用js
    Java8 的 Stream API 的确牛X,但性能究竟如何呢?
    Java 生成二维码实战
    Java高并发之设计模式,设计思想
    NullPointerException 的处理新方式,Java14 真的太香了!
  • 原文地址:https://www.cnblogs.com/Mr-Simple001/p/12106410.html
Copyright © 2011-2022 走看看