Router

路由

<body>
<div id="box">
    <div>
        <router-link to="/home">Home</router-link>
        <!--router-link用來展示組件導航-->
        <!--to屬性用于指定鏈接-->
        <!--<router-link>標簽會默認被渲染成a標簽-->
        <!--當前被點擊的路由會自帶.router-link-active屬性-->
        <router-link to="/news">News</router-link>
    </div>
    <div>
        <!--路由出口,路由默認會被渲染在這里-->
        <router-view></router-view>
    </div>
</div>
</body>
<script>
    //創(chuàng)建路由組件
    var Home = {
            template: "<h4>我是主頁</h4>"
        },
        News = {
            template: "<h4>我是新聞</h4>"
        };
    //定義組件
    var routes=[
        {path:"/home",component:Home},
        {path:"/news",component:News},
        {path:"*",redirect:"/home"}
    ]
    //創(chuàng)建路由實例,配置路由實例
    var router=new VueRouter({
        routes:routes,
        linkActiveClass:"color"
    })
    //創(chuàng)建并將路由掛載到根實例
    new Vue({
        el:"#box",
        router:router
    })
</script>
動態(tài)路由匹配

我們經(jīng)常需要把某種模式匹配到的所有路由,全部映射到同一個組件,例如我們有一個user組件用來展示用戶信息,那么對于不同ID的用戶,我們都需要使用這個組件來渲染,那么我們就可以在vue-router的路由路勁中使用動態(tài)路徑參數(shù)來達到這個效果

body>
<div id="box">
    <div>
        <router-link to="/home/1">Home</router-link>
        <router-link to="/home/2">News</router-link>
    </div>
    <div>
        <router-view></router-view>
    </div>
</div>
<template id="home">
    <div>
        <h4>this's homr</h4>
    </div>
</template>
<template id="news">
    <div>
        <h4>this's news</h4>
    </div>
</template>
<script>
    var Home = {
            template: "#home"
        },
        News = {
            template: "#news"
        };
    var routes=[
        {path:"/home/:id",component:Home},
        {path:"/news",component:News}
    ];
   //在routes中路徑參數(shù)使用:標記,那么在匹配路由時,所有 /home/參數(shù)  格式的路徑都會被匹配到Home組件,當然也可以同時使用一個或多個 例如 /home/:id/name/:id  路徑參數(shù)使用:標記那么表示這個參數(shù)可以是任意值,:id的作用只是一個占位符,也可以使用正則來匹配,如:/:id(\\d+)
    var router=new VueRouter({
        routes:routes
    });
    new Vue({
        el:"#box",
        router:router
    })
    
//在路由中設(shè)置多段路徑參數(shù),對應(yīng)的值都會設(shè)置到$route.params中,例如:
//   /user/:username匹配到路徑/user/tom,那么我們可以通過$router.params獲取到{username:"tom"}
</script>
</body>

當我們使用路由參數(shù)時,例如從/user/foo跳轉(zhuǎn)到/user/bar時,原來的組件會被復(fù)用,這樣更加高效,但是同時也意味著組件的生命周期函數(shù)不是再被調(diào)用,如果想要對路由參數(shù)的變化做出響應(yīng)的話,可以所使用watch監(jiān)測$route對象

<script>
var User = {
            template: "#user",
            watch:{
                '$route'(to,from){
                    console.log(to);
                    console.log(from);
                    //to表示從哪個路由開始跳轉(zhuǎn)
                    //from表示跳轉(zhuǎn)到哪個路由
                    //在跳轉(zhuǎn)時會觸發(fā)$route函數(shù)
                }
            }
        }
</script>
路由嵌套

實例一

<body>
<div id="box">
    <div>
        <router-link to="/home">Home</router-link>
        <router-link to="/news">News</router-link>
    </div>
    <div>
        <router-view></router-view>
    </div>
</div>
<template id="home">
    <div>
        <h4>this's home</h4>
        <ul>
            <li>
                <router-link to="/home/tom">Tom</router-link>
                <router-link to="/home/aix">Aix</router-link>
            </li>
            <li>
                <router-view></router-view>
            </li>
        </ul>
    </div>
</template>
<template id="news">
    <div>
        <h4>this's news</h4>
    </div>
</template>

<script>
    var Home = {
            template:"#home"
        },
        News = {
            template: "#news"
        },
        Tom={
            template:`
                <p>my name's tom</p>
            `
        },
        Aix={
            template:`
                <p>my name's aix</p>
            `
        };
    var routes=[
        {
            path:"/home",
            component:Home,
            children:[
                {
                    path:"tom",
                    component:Tom
                },
                {
                  path:"aix",
                    component:Aix
                }
            ]
        },
        {path:"/news",component:News}
    ]

    var router=new VueRouter({
        routes
    })

    new Vue({
        router
    }).$mount("#box")
</script>
</body>

實例二

<body>
<div id="box">
    <div>
        <h5>
            <router-link to="/user/foo">A</router-link>
            <router-link to="/user/foo/bar">B</router-link>
            <router-link to="/user/foo/cat">C</router-link>
        </h5>
        <router-view></router-view>
    </div>
</div>
<script>
    const User = {
        template: `
        <div>
            <p>{{$route.params.id}}</p>
            <router-view></router-view>
        </div>
        `
    }
    const userHome = {
        template: `
        <div>Home</div>
    `
    }
    const bar = {
        template: `
        <div>A</div>
        `
    }
    const cat = {
        template: `
            <div>
                 <div>{{$route.matched}}</div>
                 <div>B</div>
            </div>
       `
    }
    const router = new VueRouter({
        routes: [
            {
                path: "/user/:id",
                component: User,
                children: [
                    {path: "", component: userHome},
                    {path: "bar", component: bar},
                    {path: "cat", component: cat}
                ]
            }
        ]

    })

    new Vue({
        router
    }).$mount("#box")
</script>
</body>
編程式導航

在vue中我們除了使用<router-link>創(chuàng)建a標簽來定義導航鏈接,還可以杰作router的實例方法,通過編寫代碼來實現(xiàn),我們使用router-link標簽時,實際在內(nèi)部會調(diào)用router.push方法,所以說點擊<router-link :to="/home">等同于調(diào)用router.push("/home")

<body>
<div id="box">
    <div>
        <li @click="home">Home</li>
        <li @click="news">News</li>
    </div>
    <div>
        <router-view></router-view>
    </div>
</div>

<script>
    const Home = {
        template: `
                <div>
                    <h3>this's Home</h3>
                 </div>
            `
    };
    const News = {
        template: `
                <div>
                    <h3>this's News</h3>
                </div>
            `
    };

    const router = new VueRouter({
        routes: [
            {path: "/home", component: Home},
            {path: "/news", component: News}
        ]
    })

    new Vue({
        router,
        methods: {
            home() {
                router.push("/home")
            },
            news() {
                router.push("/news")
            }
        }
    }).$mount("#box")
</script>
</body>
  • router.push()

    該方法回想histiry棧添加一個新的記錄,所以當用戶點擊瀏覽器后退按鈕時,會回到之前的URL

  • router.repalce()

    該方法和router.push相似,唯一不同在于,它不會向history添加新紀錄,而是替換掉當前的history記錄,所以用戶不能點擊瀏覽器后退按鈕,該方法相當于<router-link :to="..." replace>

  • router.go(n)

    該方法的參數(shù)是一個整數(shù),意思實在history記錄中向前或者后退多掃不,類似window.history.go(n),如果瀏覽器history記錄本身小于n,那么會失敗,并且不會返回失敗信息

push以及replate的參數(shù)可以是一個字符串路徑,或則一個描述的對象:

//字符串
router.push("/home")
//對象
router.push({psth:"/home"})
//命名的路由
router.push({name:"user",params:{userId:123}})
//帶查詢參數(shù),變成/register?plan=private
router.push({path:'register',query:{plan:'private'}})
命名路由

有時候,通過一個名稱來表示一個路由顯的更方便一些,特別是在鏈接一個路由或執(zhí)行一些跳轉(zhuǎn)的時候,我們可以在創(chuàng)建Router實例的時候,在routers配置中給某個路由設(shè)置名稱

<body>
<div id="box">
    <div>
        <router-link :to="{name:'home',params:{homeId:123}}">Hmoe</router-link>
        <!--params表示傳入的動態(tài)路由homeId的參數(shù)123,該參數(shù)會傳入到路由的url地址中-->
        <router-link :to="{name:'news'}">ews</router-link>
    </div>
    <div>
        <router-view></router-view>
    </div>
</div>
<script>
    const Home = {
            template: `
            <div>
                <h5>this's Home</h5>
            </div>
        `
        },
        News = {
            template: `
            <div>
                <h5>this's News</h5>
            </div>
        `
        };

    var router = new VueRouter({
        routes: [
            {
                path: "/home/:homeId",
                name: "home",
              //在router中為路由設(shè)置名稱后,在router-link中:to 直接接受路由名稱即可
                component: Home
            },
            {
                path:"/news",
                name:"news",
                component:News
            }
        ]
    })

    new Vue({
      router
    }).$mount("#box")
</script>
</body>
命名視圖

如果我們想要同時在統(tǒng)計展示多個視圖,而不是嵌套展示,例如創(chuàng)建一個布局,有導航欄和主內(nèi)容兩個視圖,我們可以使用命名視圖,利用命名視圖我們可以在界面中擁有多個單獨命名的視圖,而不是只有一個單獨的出口,如果router-view標簽沒有設(shè)置名字,那么默認為default

<style>
    .nav {
        width: 100%;
        height: 40px;
        color: forestgreen;
        }
    .main {
        width: 100%;
        height: 100px;
        color: forestgreen;
        border: 1px solid #000;
        }
</style>
</head>
<body>
<div id="box">
    <div>
        <router-link to="/nav">Nav</router-link>
        <router-link to="/main">Main</router-link>
    </div>
    <div>
        <router-view name="navView" class="nav"></router-view>
        <router-view name="mainView" class="main"></router-view>
    </div>
</div>
<script>
    const Nav = {
            template: `
                <div>
                    <h5>this's nav</h5>
                </div>
            `
        },
        Main = {
            template: `
                <div>
                    <h5>this's main</h5>
                </div>
            `
        };
    const router=new VueRouter({
        routes:[
            {
                path:"/nav",
                components:{
                    "navView":Nav
                }
            },
            {
                path:"/main",
                components:{
                    "mainView":Main
                }
            }
        ]
    })
    new Vue({
        router
    }).$mount("#box")
</script>
</body>
重定向和別名

重定向是指將當前路由的指向重新定位到其它路由上,使用redirect來實現(xiàn)

const router=new VueRouter({
  routes:[
    {path:"/a",
    redirect:"/b"}
    //此時的/a的路由點擊會被重定向到/b路由上
  ]
})
//一般我們使用重定向來進行初始化頁面的展示
{ path:"*",redirect:"/b"}
//重定向也可以傳入一個路由名稱
{path:"/a",redirect:"{name:'b'}"}

別名和重定向的大致作用是類似的,但是區(qū)別在與

使用重定向時當用戶訪問/a時,匹配路由為/b,URL地址中也會被替換為/b

使用別名時當用戶訪問/a時,匹配的路由為/b,但是URL地址中不會被替換,依然是/a,就像用戶訪問/a一樣

const router=new VueRouter({
  routes:[
    path:"/a",
    alias:"/b"
  ]
})
導航鉤子

vue-router提供了導航鉤子主要用來攔截導航,或則完成跳轉(zhuǎn)或取消,vue-router的導航鉤子會在路由發(fā)生改變時執(zhí)行,有多種方式可以在路由發(fā)生改變時執(zhí)行鉤子:全局的,單個路由獨享的,或者是組件級的

  • 全局鉤子

    使用router.beforeEach注冊一個全局的before鉤子

    const router=new VueRouter({...})
    router.beforeEach((to,form,next)=>{
      .....
    })
    

    當一個導航觸發(fā)時,全局的before鉤子會按照創(chuàng)建順序調(diào)用,鉤子是異步解析執(zhí)行,此時導航在所有鉤子執(zhí)行完之前一直處于等待中

    每個鉤子接收三個參數(shù):

    • to 表示將要進入的目標路由對象
    • form 表示當前導航將要離開的路由
    • next 如果了解node的話可以理解為node中的next()中間件,next()表示進行下一個導航,next(false)表示中斷當前的導航,也就是不再執(zhí)行下一個跳轉(zhuǎn)導航的操作,next("/")或者next({path:"/",...})表示跳轉(zhuǎn)到我們指定的導航

    一定要注意,一定要調(diào)用next()方法,否則之后的操作都不會被執(zhí)行

    同樣可以注冊一個全局的after鉤子,不過它沒有next方法,不能改變導航

    router.afterEach(function (to,form) {
      console.log(to);
      console.log(form);
      alert("離開"+form.fullPath+",進入"+to.fullPath);
    })
    
  • 單個路由的鉤子

    通過為單個路由設(shè)置beforeEnter方法,該方法接收的參數(shù)和beforeEach是一樣的

     const router = new VueRouter({
            routes: [
                {
                    path: "/home",
                    component: Home,
                    children: [
                        {
                            path: "info",
                            component: Info,
                            meta: { requiresAuth: true,age:18 },
                            beforeEnter:function (to,form,next){
                                console.log(to);
                                console.log(form);
                                next();
                            }
                        },
                        {path: "set", component: Set}
                    ]
                },
                {path: "/news", component: News}
            ]
        })
    

    同樣需要注意一定調(diào)用next(),否則不會進入到該導航

  • 組件內(nèi)的鉤子

    也可以在路由組件內(nèi)直接定義導航鉤子

    • beforeRouteEnter
    • beforeRouteUpdata(2.2)
    • beforeRouteLeave
 News = {
            template: `
            <div>
                <h4>this's News</h4>
            </div>
        `,
            data() {
                return {
                    msg: 1
                }
            },
            beforeRouteEnter: function (to, form, next) {
                //注意在這里不能調(diào)用實例的this,因為該方法是在組件被創(chuàng)建之前調(diào)用的,所以此時實例是不存在的
                next(vm => {
                    console.log(vm.$data.msg);
                });
                //但是可以通過為next傳入一個回調(diào),把組件實例作為回調(diào)參數(shù)的方法來訪問組件的實例
            },
            beforeRouteUpdate:function (to,form,next) {
                //該方法只有在當前組件被復(fù)用時會調(diào)用
                //例如,對于一個帶有動態(tài)參數(shù)的路徑,foo/:id,在foo/1和foo/2之間跳轉(zhuǎn)的時候
                //由于會渲染同樣的foo組件,因此逐漸實例會被復(fù)用,而這個鉤子會被調(diào)用,類似動態(tài)組件中的watch
                //可以訪問實例的this
            },
            beforeRouteLeave:function(to,form,next) {
                //在導航離開組件的對應(yīng)路由時調(diào)用
                //可以訪問組件實例this
                //這個鉤子通常用于在用戶還未保存修改錢突然離開,可以通過next(false)來取消導航
            }
        }
路由元信息

定義路由的時候可以定義路由的meta字段,在meta中定義的字段,可以在路由記錄中獲取,可以用來對對每個路由進行配置,在vue中,我們稱呼router配置中的每個路由對象為路由記錄,路由記錄可以是嵌套的,因此,當一個路由匹配成功后,它可能匹配多個路由記錄,例如我們匹配到/foo/bar這個URL將會匹配副路由記錄以及自路由記錄,一個路由匹配到的所有路由記錄會暴露為$route.matched數(shù)組,因此,我們可以遍歷$$router.matched來檢查路由記錄中的meta字段

  const router = new VueRouter({
    routes: [
            {
               path: "/home",
                  component: Home,
                  children: [
                      {
                          path: "info",
                          component: Info,
                          meta: {
                              requiresAuth: true,
                              title:"主頁"
                          }
                      },
                      {path: "set", component: Set}
                  ]
              },
              {path: "/news", component: News}
          ]
    })
  ...........

  router.beforeEach((to,form,next)=>{
    if(to.matched.some(record => record.meta.requiresAuth)){
        //if的判斷條件是用來判斷meta中設(shè)置的requiresAuth變量是否為true
        //可以用來判斷該頁面是否需要用戶登錄才能進入該頁面
        //如果我們設(shè)置一個路由的meta中requiresAuth變量為true,在全局路由鉤子函數(shù)執(zhí)行的時候都會進入if判斷
        console.log(to.matched.some(record => record.meta.requiresAuth));//true
        //meta中設(shè)置的值也可以用來保存該路由中的信息,例如在meta中設(shè)置title屬性和值,在進入該頁面的時候獲取該title值設(shè)置到頁面中等操作
             document.getElementById("test").innerText=to.meta.title;
        if(用戶沒有登錄){
            next("/login"); //跳轉(zhuǎn)到登錄頁面
        }else {
            next()
        }
    }else{
        next()
          //如果該頁面不需要登錄操作,執(zhí)行用戶操作
    }
  })

注意,在to和form中我們可以獲取到跳轉(zhuǎn)的路由的信息,下面是打印的to的信息:

{name: undefined, meta: {…}, path: "/home/info", hash: "", query: {…}, …}

滾動行為

使用前端路由,當我們切換到新路由時,想要頁面滾動到頂部,或者是保持原先的滾動位置,就像重新加載頁面那樣,vue-router提供了更好的方法來讓自定義路由切換頁面是如何滾動

注意,這個功能只在HTML5 history模式下可用

在創(chuàng)建一個router實例的時候,可以提供一個scrollBehavior方法,該方法會在用戶進行路由切換時觸發(fā)

const router=new VueRouter({
        routes:[
            {
                path:"/",
                component:Home
            }
        ],
        scrollBehavior(to,form,savedPosition){
        //scrollBehavior方法接收to,form路由對象,第三個參數(shù)savedPosition當且僅當在瀏覽器前進后退按鈕觸發(fā)時才可用
        //該方法會返回滾動位置的對象信息,如果返回一個布爾假肢,或者是一個空的對象,那么不會發(fā)生滾動
        //我們可以在該方法中設(shè)置返回值來指定頁面的滾動位置,例如:
         return {x:0,y:0}
        //表示在用戶切換路由時讓是所有頁面都返回到頂部位置
        //如果返回savedPosition,那么在點擊后退按鈕時就會表現(xiàn)的像原生瀏覽器一樣,返回的頁面會滾動過到之前按鈕點擊跳轉(zhuǎn)的位置,大概寫法如下:
         if(savedPosition){
            return savedPosition
         }else{
           return {x:0,y:0}
         }
         //如果想要模擬滾動到錨點的行為:
         if(to.hash){
           return {
             selector:to.hash
           }
         }
     }
})
router-link屬性
  • to

    表示目標路由的鏈接,當被點擊時,內(nèi)部會立刻把to的值傳到router.push(),通過to傳遞的鏈接會被保存在history記錄中,所以可以使用瀏覽器回退

  • replace

    如果設(shè)置replace屬性的話,當路由被點擊時,會調(diào)用router.replace(),本次操作不會留下history記錄

    <router-link to="/home" replace></router-link>
    
  • append

    在設(shè)置append屬性后,則表示正在當前相對路徑前添加路徑,例如我們是從/a導航到/b,那么在設(shè)置了append屬性后路由導航會跳轉(zhuǎn)到/a/b,而不是/b

    <router-link to="a" append>a</router-link>  //注意不要寫/a的形式
    
  • tag

    如果想要把router-link渲染成除a外的其它標簽,可以使用tag來指定渲染之后應(yīng)該是哪種標簽,同樣他還是會監(jiān)聽點擊,觸發(fā)導航

    <router-link to="/home" tag="li"></router-link>
    
  • exact

    表示是否激活全局,可以理解為如果一個導航的路徑是/home開頭的,并且我們設(shè)置了點擊樣式,在/home路徑的導航設(shè)置了exact的情況下所有以、home開頭的路徑的導航的樣式都會同時改變

    https://jsfiddle.net/8xrk1n9f/ 這是vue官方的一個簡單直觀的例子

  • 將激活時的css類名應(yīng)用在外層元素

    有時候我們需要讓css類應(yīng)用在外層元素,而不是a標簽本身,那么可以用router-link渲染外層元素,包裹著內(nèi)層原生a標簽

    <router-link tag="li" to="/home">
      <a>Home</a>
    </router-link>
    

    這種情況下,a將作為真實的鏈接,它會獲得正確的href,而激活時的css類名則會設(shè)置到外層的li

  • events
    用來可以用來觸發(fā)導航的事件,默認是"click"

router-view屬性
  • name
    如果 <router-view>設(shè)置了名稱,則會渲染對應(yīng)的路由配置中 components 下的相應(yīng)組件
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • vue2有著深度繼承的路由插件,即:vue-router,其中文的API地址。 vue-router與其他的路由(...
    白水螺絲閱讀 17,688評論 0 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,590評論 19 139
  • 用Vue.js + vue-router創(chuàng)建單頁應(yīng)用,是非常簡單的,基本是這樣的: 組件 → 路由 → 渲染地方 ...
    阿go閱讀 1,451評論 0 0
  • github地址,歡迎大家提交更新。 express() express()用來創(chuàng)建一個Express的程序。ex...
    Programmer客棧閱讀 2,828評論 0 1
  • 心理學書籍,必定閱讀者和作者之間的無數(shù)交鋒,才能將原本狀態(tài)的心,重新辯識一番,遇見更好的自己。反觀全書,這本書是能...
    NatureBig閱讀 573評論 2 2

友情鏈接更多精彩內(nèi)容