zoukankan      html  css  js  c++  java
  • Vue.js之vue-router路由

    vue学习的一系列,全部来自于表哥---表严肃,是我遇到过的讲课最通透,英文发音最好听的老师,想一起听课就去这里吧 https://biaoyansu.com/i/hzhj1206

    1概述

    vue-router是vue的一个库,可以快速的开发一个单页应用;

    在导航切换时,页面根本就不刷新,没有整页刷新的概念,所以用户的输入可以被保留下来,不丢失状态,不丢失数据;

    不用每切换一次导航就重新拉取一遍数据,只需要取一次数据,就可以一直用;

    在网页上最频烦的操作就是点点点,这样页面不刷新,就可以极大的节省前端和后端的资源。

    2安装和基本配置

    引用vue文件和vue-router的库文件,https://cdn.bootcss.com/vue-router/3.0.6/vue-router.js

    例:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>路由</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router            
            })
        </script>
    </html>

     

    配置说明:

    定义一个数组rounts,数组中的每一项都是一个配置,path代表路由的地址,/就表示首页(默认页);可以直接传进一个component,这个component和普通的component一样,该有的功能都可以用;

    然后把定义的规则传给构造的路由,var router=new VueRouter();定义一个routes,把数组传给它就可以了;

    在new Vue中加一个router属性,把定义的构造器router传进去;

    html中,要加一个标签router-link,用to指定地址,再用router-view表示显示的视图,它显示的就是template中定义的内容

    3传参及获取传参

    vue-router中传参有两种方式,

    第一种,User后面加个冒号:/user/:name,在template中通过{{$route.params.name}}来获取。

    例:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>路由-传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                    <router-link to="/user/大美女">大美女</router-link>
                    <router-link to="/user/小东西">小东西</router-link>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                },
                {
                    path:'/user/:name',
                    component:{
                        template:`
                        <div>
                            <p>我叫{{$route.params.name}}</p>
                            <!-- <p>我今年{{$route.query.age}}岁</p> -->
                        </div>
                        `
                    }
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router            
            })
        </script>
    </html>

    第二种,通过query,就是地址后面跟着?这样,例如:

    http://127.0.0.1:8848/vuetest.html?age=20#/,在template中把params换成query就可以了,{{$route.query.age}}

    例:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>路由-传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                    <router-link to="/user/大美女">大美女</router-link>
                    <router-link to="/user/小东西">小东西</router-link>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                },
                {
                    path:'/user/:name',
                    component:{
                        template:`
                        <div>
                            <p>我叫{{$route.params.name}}</p>
                            <p>我今年{{$route.query.age}}岁</p>
                        </div>
                        `
                    }
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router            
            })
        </script>
    </html>

    4子路由

    在上面例子的基础上,想实现“大美女后面加个/more,就是嵌套的路由,

    再加一个children的配置项,代表子路由,也是一个数组,写法和父级的rounts一样,path可以写成more,传参写法也一样,$route.params.name。

    然后在父级路由添加链接<router-link>,这里的to的写法有两种方式:

    一种是用v-bind,中间动态的部分就用传参的形式写,

    :to="'/user/'+$route.params.name+'/more'",就类似这样的。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>路由-传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                    <router-link to="/user/大美女">大美女</router-link>
                    <router-link to="/user/小东西">小东西</router-link>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                },
                {
                    path:'/user/:name',
                    component:{
                        template:`
                        <div>
                            <p>我叫{{$route.params.name}}</p>
                            <router-link :to="'/user/'+$route.params.name+'/more'">更多</router-link>
                               <router-view></router-view>
                        </div>
                        `
                    },
                    children:[{
                        path:'more',
                        component:{
                            template:`
                        <div>
                            用户 {{$route.params.name}} 的详细信息:内容内容在这里写很多...
                        </div>
                        `
                        }
                        
                    }
                    ]
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router            
            })
        </script>
    </html>

    另一种比较简洁,to的值直接写成more,然后给router-link加个属性append,表示追加的意思,这样就是在原来的后面加上一个more了,但是这种写法只能点击一次,再点“更多”,就又会多追加一个/more

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>路由-传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                    <router-link to="/user/大美女">大美女</router-link>
                    <router-link to="/user/小东西">小东西</router-link>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                },
                {
                    path:'/user/:name',
                    component:{
                        template:`
                        <div>
                            <p>我叫{{$route.params.name}}</p>
                            <router-link to="more" append>更多</router-link>
                               <router-view></router-view>
                        </div>
                        `
                    },
                    children:[{
                        path:'more',
                        component:{
                            template:`
                        <div>
                            用户 {{$route.params.name}} 的详细信息:内容内容在这里写很多...
                        </div>
                        `
                        }
                        
                    }
                    ]
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router            
            })
        </script>
    </html>

    5手动访问和传参

    5.1手动访问

    想实现,点击某个按钮,button,加个点击事件,每隔一秒去访问一个链接,这样用户只点一次,就自动访问设置的链接了,使用this.router.pushpush这个接口就是专门用来访问某个链接的,写在push中的链接就被推到了历史记录中,

    :

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>手动访问和传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                    <router-link to="/user/大美女">大美女</router-link>
                    <router-link to="/user/小东西">小东西</router-link>
                    <button @click="surf">漫游</button>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                },
                {
                    path:'/user/:name',
                    component:{
                        template:`
                        <div>
                            <p>我叫{{$route.params.name}}</p>
                            <router-link to="more" append>更多</router-link>
                               <router-view></router-view>
                        </div>
                        `
                    },
                    children:[{
                        path:'more',
                        component:{
                            template:`
                        <div>
                            用户 {{$route.params.name}} 的详细信息:内容内容在这里写很多...
                        </div>
                        `
                        }
                        
                    }
                    ]
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router,
                methods:{
                    surf:function(){
                        setTimeout(function(){
                            this.router.push('/about');
                            setTimeout(function(){
                                this.router.push('/user/大美女');
                            },2000);
                        },2000);
                    }
                }
            })
        </script>
    </html>

     

    这种手动触发的方式,虽然比较麻烦,但能做到更细粒度的控制,做出来的功能可以很强大,

    router-link方式更方便简单,多数情况下还是用router-link

    5.2手动传参

    push中直接传一个对象,{name:’user’},这里的name指的是路由的名称,是在上面写规则那里指定的name,

     

    然后传参可以写在params里,也是一个对象params:{name:'大美女'}

    完整示例:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>手动访问和传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/about">关于</router-link>
                    <router-link to="/user/大美女">大美女</router-link>
                    <router-link to="/user/小东西">小东西</router-link>
                    <button @click="surf">漫游</button>
                </div>
                <div>
                    <router-view></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/about',
                    component:{
                        template:`
                        <div><h1>关于</h1></div>
                        `
                    }
                },
                {
                    path:'/user/:name',
                    name:'user',
                    component:{
                        template:`
                        <div>
                            <p>我叫{{$route.params.name}}</p>
                            <router-link to="more" append>更多</router-link>
                               <router-view></router-view>
                        </div>
                        `
                    },
                    children:[{
                        path:'more',
                        component:{
                            template:`
                        <div>
                            用户 {{$route.params.name}} 的详细信息:内容内容在这里写很多...
                        </div>
                        `
                        }
                        
                    }
                    ]
                }
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router,
                methods:{
                    surf:function(){
                        setTimeout(function(){
                            this.router.push('/about');
                            setTimeout(function(){
                                this.router.push({
                                    name:'user',
                                    params:{
                                        name:'大美女'
                                    }
                                });
                            },2000);
                        },2000);
                    }
                }
            })
        </script>
    </html>

    6命名视图

    如果页面中有两个router-view,可以用name属性进行区分,

    然后写rounts时,把原来的component换成components,也是一个对象,键就是name,值又是一个对象,在对象里面定义template,例:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>路由-传参</title>
        </head>
        <body>
            <div id="app">
                <div>
                    <router-link to="/">首页</router-link>
                    <router-link to="/user">用户管理</router-link>
                    <router-link to="/post">文章管理</router-link>
                </div>
                <div>
                    <router-view></router-view>
                    <router-view name="sidebar"></router-view>
                    <router-view name="content"></router-view>
                </div>
            </div>
        </body>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <script>
            var rounts=[
                {
                    path:'/',
                    component:{
                        template:`
                        <div><h1>首页</h1></div>
                        `
                    }
                },
                {
                    path:'/user',
                    components:{
                        sidebar:{
                            template:`
                            <div>
                                <ul>
                                    <li>用户1</li>
                                    <li>用户2</li>
                                </ul>
                            </div>
                            `
                        },
                        content:{
                            template:`
                            <div>
                                内容1在这里...
                            </div>
                            `
                        },
                    }
                },
                {
                    path:'/post',
                    components:{
                        sidebar:{
                            template:`
                            <div>
                                <ul>
                                    <li>文章1</li>
                                    <li>文章2</li>
                                </ul>
                            </div>
                            `
                        },
                        content:{
                            template:`
                            <div>
                                内容2在这里...
                            </div>
                            `
                        },
                    }
                },
                
            ];
            
            var router=new VueRouter({
                routes:rounts
            });        
            
            var app=new Vue({
                el:'#app',
                router:router            
            })
        </script>
    </html>

    想命名多少个router-view都可以,但不建议命名太多,不好维护,一个页面2-5个比较合适。

    7导航钩子 

    状态和权限的检查,最好在路由层面就检查好,该驳回的驳回,该访问的访问,这样节省资源。而不要再到组件级别去检查,因为页面中组件太多。 

    例: 

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>导航钩子</title>
    </head>
    <body>
    
    <div id="app">
        <div>
            <router-link to="/">首页</router-link>
            <router-link to="/login">登录</router-link>
            <router-link to="/post">帖子管理</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
    
    <script src="lib/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <script>
    var rounts=[
        {
            path:'/',
            component:{
                template:`
                <h1>首页</h1>
                `
            }
        },
        {
            path:'/login',
            component:{
                template:`
                <h1>登录</h1>
                `
            }
        },
        {
            path:'/post',
            component:{
                template:`
                <h1>帖子管理</h1>
                `
            }
        }
    ];
    
    var router=new VueRouter({
        routes:rounts
    });
        
        
    var zyx=new Vue({
        el:'#app',
        router:router
    });
    </script>
    </body>    
    </html>

     

     

    现在想实现,访问“帖子管理”时,会进行检查, 

    vue中通过router的实例的一个方法beforeEach实现, 

    参数说明: 

    to,表示到哪里去 

    from,表示从哪里来 

    next,指定接下来要怎么做: 

      直接next();就是正常执行, 

      如果next(false);那么所有的路由都不工作了, 

      还可以传个地址, next('/login');

    例: 

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>导航钩子</title>
    </head>
    <body>
    
    <div id="app">
        <div>
            <router-link to="/">首页</router-link>
            <router-link to="/login">登录</router-link>
            <router-link to="/post">帖子管理</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
    
    <script src="lib/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <script>
    var rounts=[
        {
            path:'/',
            component:{
                template:`
                <h1>首页</h1>
                `
            }
        },
        {
            path:'/login',
            component:{
                template:`
                <h1>登录</h1>
                `
            }
        },
        {
            path:'/post',
            component:{
                template:`
                <h1>帖子管理</h1>
                `
            }
        }
    ];
    
    var router=new VueRouter({
        routes:rounts
    });
    
    router.beforeEach(function(to,from,next){
        //是否登录
        var logged_in=false;
        //如果没登录并且要访问post
        if(!logged_in && to.path=='/post'){
            //转到登录页
            next('/login');
        }else{
            //正常执行
            next();
        }
    });
        
    var zyx=new Vue({
        el:'#app',
        router:router
    });
    </script>
    </body>    
    </html>

    如果logged_infalse,那么点击帖子管理会跳到登录页,为true时才会正常访问

    说白了这就是个中间件,也可称为路由的生命周期。

    还可以在访问之后进行操作,用router.afterEach,其参数只有tofrom,不大常用。因为表示路由已加载完毕,可以真正运行这个路由下的所有组件了,那么就可以在这里发送一些全局的异步请求,写一些业务逻辑。这里面的内容放到组件的生命周期也可以。 

    例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>导航钩子</title>
    </head>
    <body>
    
    <div id="app">
        <div>
            <router-link to="/">首页</router-link>
            <router-link to="/login">登录</router-link>
            <router-link to="/post">帖子管理</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
    
    <script src="lib/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <script>
    var rounts=[
        {
            path:'/',
            component:{
                template:`
                <h1>首页</h1>
                `
            }
        },
        {
            path:'/login',
            component:{
                template:`
                <h1>登录</h1>
                `
            }
        },
        {
            path:'/post',
            component:{
                template:`
                <h1>帖子管理</h1>
                `
            }
        }
    ];
    
    var router=new VueRouter({
        routes:rounts
    });
    
    router.beforeEach(function(to,from,next){
        //是否登录
        var logged_in=true;
        //如果没登录并且要访问post
        if(!logged_in && to.path=='/post'){
            //转到登录页
            next('/login');
        }else{
            //正常执行
            next();
        }
    });
    
    router.afterEach(function(to,from){
        console.log('to:',to);
        console.log('from:',from);
    });
        
    var zyx=new Vue({
        el:'#app',
        router:router
    });
    </script>
    </body>    
    </html>

    8元数据及路由匹配

    还是上面的登录的例子,如果帖子管理中还有子路由,地址是/post/article

    如果没有登录,那么post/”后面所有内容,都是不能访问的,

    可以使用to的属性matched,意思是匹配了的路由,

    例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>元数据及路由匹配</title>
    </head>
    <body>
    
    <div id="app">
        <div>
            <router-link to="/">首页</router-link>
            <router-link to="/login">登录</router-link>
            <router-link to="/post">帖子管理</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
    
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <script>
    var rounts=[
        {
            path:'/',
            component:{
                template:`
                <h1>首页</h1>
                `
            }
        },
        {
            path:'/login',
            component:{
                template:`
                <h1>登录</h1>
                `
            }
        },
        {
            path:'/post',
            component:{
                template:`
                <div>
                    <h1>帖子管理</h1>
                    <router-link to="article" append>文章一</router-link>
                    <router-view></router-view>
                </div>
                `
            },
            children:[
                {
                    path:'article',
                    component:{
                        template:`<h2>文章一的内容...</h2>`
                    }
                }
            ]
        }
    ];
    
    var router=new VueRouter({
        routes:rounts
    });
    
    router.beforeEach(function(to,from,next){
        //是否登录
        var logged_in=false;
        //如果没登录并且要访问post
        if(!logged_in && to.matched.some(function(item){
            return item.path=='/post';
        })){
            //转到登录页
            next('/login');
        }else{
            //正常执行
            next();
        }
    });
        
    var zyx=new Vue({
        el:'#app',
        router:router
    });
    </script>
    </body>    
    </html>

    访问/post/post/article都是跳到登录页

     

    Tipssome方法,

    some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。

    some() 方法会依次执行数组的每个元素:

    如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。

    如果没有满足条件的元素,则返回false

    详情:https://www.runoob.com/jsref/jsref-some.html

    还有第二种方法,如果页面中有非常多的路由,不可能一个个的都去写匹配,太麻烦,那么可以在路由的配置中来写,可以加一个meta的配置,元数据的意思,可以在meta中自定义一个login_required:true,然后return item.meta.login_required; 这样只要路由加上了这个配置,就能控制登录权限了,不用每一个都去js中判断了。

    例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>元数据及路由匹配</title>
    </head>
    <body>
    
    <div id="app">
        <div>
            <router-link to="/">首页</router-link>
            <router-link to="/login">登录</router-link>
            <router-link to="/post">帖子管理</router-link>
            <router-link to="/test">新加测试</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
    
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <script>
    var rounts=[
        {
            path:'/',
            component:{
                template:`
                <h1>首页</h1>
                `
            }
        },
        {
            path:'/login',
            component:{
                template:`
                <h1>登录</h1>
                `
            }
        },
        {
            path:'/post',
            meta:{
                login_required:true
            },
            component:{
                template:`
                <div>
                    <h1>帖子管理</h1>
                    <router-link to="article" append>文章一</router-link>
                    <router-view></router-view>
                </div>
                `
            },
            children:[
                {
                    path:'article',
                    component:{
                        template:`<h2>文章一的内容...</h2>`
                    }
                }
            ]
        },
        {
            path:'/test',
            meta:{
                login_required:true
            },
            component:{
                template:`
                <h1>测试</h1>
                `
            }
        }
    ];
    
    var router=new VueRouter({
        routes:rounts
    });
    
    router.beforeEach(function(to,from,next){
        //是否登录
        var logged_in=false;
        //如果没登录并且要访问post
        if(!logged_in && to.matched.some(function(item){
            return item.meta.login_required;
        })){
            //转到登录页
            next('/login');
        }else{
            //正常执行
            next();
        }
    });
        
    var zyx=new Vue({
        el:'#app',
        router:router
    });
    </script>
    </body>    
    </html>

  • 相关阅读:
    使用 HTML5 可以做的五件很棒的事情
    分享最新20款非常棒的 CSS 工具
    最新17个紫色风格网页设计作品欣赏
    最新70佳很酷的名片设计作品欣赏
    50个优秀的名片设计作品欣赏
    推荐12个漂亮的CSS3按钮实现方案
    推荐10个很棒的 CSS3 开发工具
    30个复古风格的网页设计作品欣赏
    非常流行的十款 jQuery 插件推荐
    20个漂亮的WordPress作品集主题分享
  • 原文地址:https://www.cnblogs.com/hzhjxx/p/10878009.html
Copyright © 2011-2022 走看看