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>

 


免責聲明!

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



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