Vue-router单页面

814 阅读3分钟

vue路由绝对是vue中的一大块,基本上路由都有两大模式history模式和hash模式,而我们常用的则是history模式

  1. vue-router

    默认的路由使用的hash模式 (http://localhost:8080/#/page1)
    • 起步 :安装vue-router模块

      npm install vue-router --save
      
    • 新建router.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中进行使用插件,赋予vue控制路由的能力

      import VueRouter from 'vue-router';
      import router from './routes';
      Vue.use(VueRouter); //将this.$router 挂载到原型链上,使得vue具有处理路由的能力
      new Vue({
          router,
          render: h => h(App),
      }).$mount('#app');
      
    • 在App.vue中使用 ,使用router-view 标签进行占位

      <!--路由占位符-->
      <router-view></router-view>
      
    • 按钮导航,

      <router-link to="/page1" class="page1">页面1</router-link>
      <router-link to="/page2" class="page2">页面2</router-link>
      
    history模式:

    默认是hash 模式的路由,url 使用#后面定位路由,对SEO不利,设置history模式可以使用普通的url

    //直接在routes.js中配置 mode:
    export default new VueRouter({
        mode:"history",
        routes:[
            {path:'/page1',component:Page1},
            {path:'/page2',component:Page2},
        ]
    })
    
    
    动态路由:

    在配置路由的使用:id占位符,和angualar类似 ,一些参数可以使用this.$route.XX进行获取

    export default new VueRouter({
        mode:"history",
        routes:[
            {path:'/page1',component:Page1},
            {path:'/page2',component:Page2},
            {path:'/page3/:id',component:Page3},
        ]
    })
    // ---------进行获取
    computed:{
        name(){
            return this.$route.params.id
        }
    }
    

    这种获取路由参数比较麻烦,更优雅的方式获取,使用属性传递的方式进行获取

    export default new VueRouter({
        mode:"history",
        routes:[
            {path:'/page1',component:Page1},
            {path:'/page2',component:Page2},
            {path:'/page3/:id',props:true,component:Page3}, // 使用props 表示属性传递
        ]
    })
    //-------在进行或去就比较优雅 ,直接使用props接收
       props:['id'],
    
    子路由嵌套
    export default new VueRouter({
        mode:"history",
        routes:[
            {path:'/login',component:Login},
            {
                path:'/dashboard',
                component:DashBoard,
                children:[      //---------子路由的嵌套
                    {path:'/page1',component:Page1},
                    {path:'/page2',component:Page2},
                    {path:'/page3/:id',props:true,component:Page3},
                ]
            },
        ]
    })
    //-------------第一层使用
      <div id="app">
        <h1>2019年,新的一天你好!!!</h1>
        <hr>
        //路由占位符
        <router-view></router-view>   <!--第一层,包含login和dashboard两个路由-->
      </div>
    //------------dashboard里边的嵌套
    <template>
        <div>
            <div class="navbar">
                <router-link to="/page1" class="page1">页面1</router-link>
                <router-link to="/page2" class="page2">页面2</router-link>
                <router-link to="/page3/vuejs" class="page2">Vue</router-link>
            </div>
            <hr>
            <router-view></router-view> <!--这是第二层,子路由嵌套在这里-->
        </div>
    </template>
    
    路由的重定向:使用redirect进行重定向
    {path:'/',redirect:'/login'},
    
    路由守卫 :(在路由跳转之前或者路由跳转之后hooks)钩子
    let let routes = new VueRouter({
        ...
    })
    routes.beforeEach((to, from, next) => {
        console.log('beforeEach',to); //  to 是和那个路由里的所有东西
        if (to.path!=='/login'){   //逻辑是如果不是login页面则随便跳转 ,但是如果是login页面则需要两秒之后跳转
            next()
        }else{
            setTimeout(()=>{
                next();
            },2000)
        }
    });
    routes.afterEach((to,from)=>{
        console.log('afterEach');
    });
    export default routes
    
    
    组件内部生命周期:上边的路由守卫是全局的 ,我们组件内部也有一些内部生命周期

    需要一些组件内部的守卫 ,有两种方法

    • 在routes配置path的时候进行,不推荐

      export default new VueRouter({
          routes:[
              {path:'/page1',component:Page1},
              {path:'/page2',component:Page2},
          ]
      })
      
    • 再组件内部 执行 推荐

      注意顺序是 ,路由守卫beforeEach ->beforeRouteEnter ->beforeRouteLeave->afterEach的顺序

      <script>
          export default {
              beforeRouteEnter(to,from,next){
                console.log('page3进来了');
                next();
              },
              beforeRouteLeave(to,from,next){
                console.log('page3准备退出了');
                if (window.confirm('您真的要退出么?')){
                    next();
                }
              },
      
          }
      </script>
      
    • 当路由组件没有变但是路由的参数变了时,比如 由 page3/vuejs变为 page3/react

      beforeRouteUpdate(to,form,next){
          console.log('page3路由,但是参数变化了');
          next();
      },
      
    整个路由的操作逻辑 ,我理解是执行顺序
    1. 导航被触发
    2. 调用全局的beforeEach守卫
    3. 在重用的组件里调用beforeRouteUpdate守卫
    4. 在路由配置里边调用beforeEnter 这个和组件里的beforeRouteEnter类似
    5. 在被激活的组件⾥调⽤ beforeRouteEnter。
    6. 调⽤全局的 beforeResolve 守卫 (2.5+)。 这个比全局的beforeEach守卫晚一点点
    7. 导航被确认。
    8. 组件的beforeRouteLeave
    9. 调用全局的 afterEach 钩子。
    10. 触发 DOM 更新。
    异步组件 ,懒加载

    路由懒加载vue中配合webpack非常简单 ,在需要懒加载的组件的路由配置中直接import()

    //比如让login组件实现懒加载
    {path:'/login',component:()=>import('./components/Login')}
    //{path:'/login',component:Login},