美文网首页VUE
day03:Vue Router

day03:Vue Router

作者: da761996934f | 来源:发表于2019-01-17 18:41 被阅读32次

    写在前面

    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
    
    • 修改一下Page2,感受一下组件内部生命周期
    <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"
            }
        ]
    })
    

    相关文章

      网友评论

        本文标题:day03:Vue Router

        本文链接:https://www.haomeiwen.com/subject/wtjqrqtx.html