VUE

day03:Vue Router

2019-01-17  本文已影响32人  da761996934f

写在前面

Vue Router 是 Vue.js 官方的路由管理器,我们用它来完成前端的路由管理。

PART01:做一个简单的导航

先安装vue-router
- vue create day03 ~ 新建今天的项目
- cd day03 ~ 进入项目
- npm install vue-router --save ~ 安装vue-router
新建两个页面
//components/Page1.vue
<template>
    <div>我是页面1</div>
</template>
<script>
    export default{
    }
</script>

//components/Page2.vue
<template>
    <div>我是页面2</div>
</template>
<script>
    export default{
    }
</script>
新建一个路由控制器
//routes.js
import VueRouter from "vue-router"
import Page1 from "./components/Page1"
import Page2 from "./components/Page2"
export default new VueRouter({
    routes : [
        {path:"/page1",component:Page1},
        {path:"/page2",component:Page2},
    ]
})
在main.js里做个引入,使用这个路由控制器
//main.js
import VueRouter from "vue-router"
import router from "./routes"

Vue.use(VueRouter)
new Vue({
    router : router,
    ……
})
在App.vue里体验一下这个小小的导航
<template>
    <div id="app">
        <div>
            <router-link to="/page1">page1</router-link>
            <router-link to="/page2">page2</router-link>
        </div>
        <hr/>
        <router-view></router-view>
    </div>
</template>
<script>
    export default{
    }
</script>

PART02:前端路由的两种模式

hash模式

hash 指的是 url后面的# 及 跟随该#的一系列字符。
hash原本是用来做页面定位的,hash值的改变不会触发请求但会触发hashchange事件。
通常我们用 监听hashchange事件修改window.location.hash值 的方式,实现hash模式。
缺点:url丑、和锚点冲突、复杂参数难传、不利于SEO。
支持:能支持到IE8。

history模式

通过window.history.pushState()和window.history.replaceState()修改url,会导致向服务器发送请求,这就是history模式。
在history里增加一条记录:window.history.pushState(state,title,url)
修改history里的一条记录:window.history.replaceState(state, title, url)
其中:state是需要保存的数据,title是标题,url是要设定的url。
另外:浏览器的前进后退会触发popstate事件,上述方法不触发该事件。
支持:这两个方法是H5新加的,所以能支持到IE10。

vue-router中的它们

默认为hash模式,可以在routes.js中修改成history模式。

//routes.js
……
export default new VueRouter({
    mode : "history",
……

PART03:动态路由

实际项目中,存在大量的动态路由,如产品页等等。
vue-router也支持通过参数传递的方式实现动态路由。

通过 this.$route 获取路由参数
//routes.js
……
export default new VueRouter({
    routes : [
        {path:"/page/:id",component:Page}
    ]
})

//App.vue
<template>
    <div id="app">
        <router-link to="/page/aaa">aaa</router-link>
        <router-link to="/page/bbb">bbb</router-link>
        <hr/>
        <router-view></router-view>
    </div>
</template>

//component/Page.vue
<template>
    <p>我是:{{name}}</p>
</template>
<script>
    export default{
        computed : {
            name(){
                return this.$route.params.id
            }
        }
    }
</script>
通过 props 获取路由参数
//routes.js
……
export default new VueRouter({
    routes : [
        {path:"/page/:id",props:true,component:Page}
    ]
})

//App.vue
<template>
    <div id="app">
        <router-link to="/page/aaa">aaa</router-link>
        <router-link to="/page/bbb">bbb</router-link>
        <hr/>
        <router-view></router-view>
    </div>
</template>

//components/Page.vue
<template>
    <div>我是:{{id}}</div>
</template>
<script>
    export default{
        props:["id"]
    }
</script>

PART04:路由嵌套

假设我们的某些页面带导航,而另一些页面不用导航。
我们又不想在每一处都写一遍,则可以使用嵌套的方式来解决。

//App.vue - 把导航搬走,只留个占位符
<template>
    <div id="app">
        <router-view></router-view>
    </div>
</template>

//components/Inner.vue - 把带导航的页统一到一起
<template>
    <div>
        <router-link to="/inner/page1">page1</router-link>
        <router-link to="/inner/page2">page2</router-link>
        <router-link to="/inner/page3/aaa">aaa</router-link>
        <hr/>
        <router-view></router-view>
    </div>
</template>

//routes.js - 把嵌套的路由,写在inner的children里
export default new VueRouter({
    routes : [
        {path:"/login",component:Login},
        {
            path:"/inner",
            component:Inner,
            children:[
                {path:"page1",component:Page1},
                {path:"page2",component:Page2},
                {path:"page3/:id",props:true,component:Page3}
            ]
        }
    ]
})

PART05:路由的生命周期

在实际项目中,我们可能需要对用户做 是否登录是否有权访问 等判断,还有可能需要做 全局Loading 等优化。
这就需要我们知道,做这些操作的时机,这就是路由生命周期的意义。

用一个小例子理顺一下
//App.vue
<template>
    <div id="app">
        <router-link to="/page1">页面1</router-link>
        <router-link to="/page2/aaa">商品aaa</router-link>
        <router-link to="/page2/bbb">商品bbb</router-link>
        <hr/>
        <router-view></router-view>
    </div>
</template>

//components/Page1.vue
<template>
    <p>我是页面1</p>
</template>

//components/Page2.vue
<template>
    <p>我是商品:{{product}}</p>
</template>
<script>
export default{
    props:["product"]
}
</script>
//routes.js
import VueRouter from "vue-router"
import Page1 from "./components/Page1"
import Page2 from "./components/Page2"
let routes =  new VueRouter({
    mode : "history",
    routes : [
        //在这里做一个首页的重定向
        {path:"/",redirect:"/page1"},
        {path:"/page1",component:Page1},
        {path:"/page2/:product",props:true,component:Page2}
    ]
})
//beforeEach - 在所有路由跳转前执行
routes.beforeEach((to,from,next)=>{
    console.log(beforeEach)
    next()
})
//beforeResolve - 在所有路由内部enter执行完后
routes.beforeResolve((to,from,next)=>{
    console.log(beforeResolve)
    next()
})
//afterEach - 在所有路由跳转后执行
routes.afterEach((to,from)=>{
    console.log(afterEach)
})
export default routes
<script>
    export default{
        props : ["product"],
        beforeRouteEnter(to,from,next){
            console.log("page2路由进入前")
            next()
        },
        beforeRouteUpdate(to,from,next){
            console.log("page2路由没变,但路由参数变了")
            next()
        },
        beforeRouteLeave(to,from,next){
            console.log("page2路由离开前")
            next()
        }
    }
</script>
- 访问:/page1
- 打印:
    beforeEach
    beforeResolve
    afterEach
- 跳转:/page2/aaa
- 打印:
    beforeEach
    beforeResolve
    page2路由进入前
    afterEach
- 跳转:/page2/bbb
- 打印:
    beforeEach
    beforeResolve
    page2路由没变,但路由参数变了
    afterEach
- 跳转:/page1
- 打印:
    page2路由离开前
    beforeEach
    beforeResolve
    afterEach

PART06:两个小技巧

nginx配置

我们一直是利用vue-cli脚手架写的项目,这里的路由监听是webpack做的。
项目发布后,就要去配置一下nginx,将所有的访问都映射到index。
这是因为我们的路由是前端控制的,如果nginx直接访问某个url,他会尝试获取这个url下的资源,会抛出404。

异步组件

我们前面加载组件的方法,都是同步的。
如果组件很多而且有些并不常用时,我们可以把它做成异步组件。
异步组件在打包的时候不会被打进去,访问的时候才会加载。

//routes.js
import VueRouter from "vue-router"
import Page1 from "./components/Page1"
export default new VueRouter({
    routes : [
        //同步组件
        {path:"/page1",component:Page1}
        //异步组件
        {
            path:"/page2",
            component:()=>import "./components/Page2"
        }
    ]
})
上一篇下一篇

猜你喜欢

热点阅读