Vue路由的使用

Vue路由

用 Vue.js + Vue Router 创建单页应用

  • 下载vue-router.js

    vue-router3.x是针对Vue2.x版本

    vue-router4.x是针对Vue3.x版本

  • 引入在vue.js的后面

1. 基础路由配置

  • 配置路由
// 定义路由组件
        const index = { template: `<div>首页</div>` }
        const list = { template: `<div>列表页</div>` }
        const cart = { template: `<div>购物车</div>` }

        // 定义路由表
        const routes = [
            { path: '/' , redirect: '/index'},
            { path: '/index' , component: index },
            { path: '/list' , component: list },
            { path: '/cart' , component: cart },
        ]
        //创建路由对象
        const router = new VueRouter({
            routes
        })

        // 注册路由
        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {},
            router
        });
  • 路由出口

    <router-view></router-view>
    
  • 路由跳转(即路由导航)

    <router-link to="/index"></router-link>
    

2. 嵌套路由

比如: 小米首页的推荐,智能、电视

{
    path: '/index',
    component: index,
    redirect: '/index/recommend',
    children: [
      {
        path: 'recommend',
        component: recommend
      },
      {
      	name: 'ai',
        path: 'ai',
        component: ai
      },
      {
        path: 'tv',
        component: tv
      }
    ]
  },

路由出口在父组件index中

<router-view></router-view>

路由导航

<router-link to="/index/recommend">推荐</router-link>

3. 动态路由

能够接收参数的路由称为动态路由

  • 配置动态路由

    const routes = [
        { path: '/detail/:id/:type' , component: detail },
    ]
    
  • 路由跳转时传参(5为id值,car为type的值)

    <router-link to="/detail/5/car"></router-link>
    
  • 在detail组件中接收参数

    let id = this.$route.params.id
    let type = this.$route.params.type
    

4. vue两种实现导航(跳转)的方式

  • 声明式导航 ,用router-link实现

    <router-link to="/list">列表页</router-link>
    
  • 编程式导航,用this.$router的API实现

    this.$router.push("/list")
    this.$router.go(-1)  : 返回上一步
    this.$router.replace("/list") : 跳转至下个页面,并替换当前页的跳转记录(go(-1)或在浏览器中单击后退按钮时会跳过上一级页面)
    

5. 命名路由

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。

const routes =  [
    {
      path: '/user/:userId',
      name: 'user',  //命名路由,该名称在路由跳转及传参中使用
      component: User
    }
  ]

6. 路由传参方式汇总

  • 声明式导航
<!-- 下面传参的方式,在跳转到的路由组件中,都是通过this.$route.query来接收, 路由不需要在router/index.js中配置参数 -->

<router-link :to="{path:'/list',query:{ id: 9} }">进入list页面</router-link>
<router-link :to="{path:'/list',query:{ id: 9,person:this.person} }">进入list页面</router-link>
<router-link to="/list?id=8">进入list页面</router-link>
<router-link to="/list?id=8&page=2">进入list页面</router-link>

<!-- name的值是在路由配置中用name属性定义的路由名称 -->
<router-link :to="{name:'list',query:{ id: 9} }">进入list页面</router-link>


<!-- 没有提前在路由中配置动态参数,直接用params传值,接收 this.$route.params.id -->
<router-link :to="{name: 'list',params: {id: 8}}">进入list页面</router-link>


<!-- 下方传参无效,path不能和params结合使用 -->
<router-link :to="{path: '/list',params: {id: 8}}">进入list页面</router-link>
  • 编程式导航

    //  编程式导航的传参方式和接收方式都和声明式导航相同
    
           this.$router.push("/list")
    
           this.$router.push({
             path: '/list'
           })
    
           this.$router.push("/list/7")  //无效,因为list没有配置动态参数
    
          this.$router.push("/list?id=9")
          
          this.$router.push({
            path: '/list',
            query: {
              id: 7,
              age: 100
            }
          })
          
          this.$router.push({
            name: 'list',
            params: {
              id: 7,
              age: 100
            }
          })
    

7. 了解命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default

<!--App.vue -->
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

一个视图使用一个组件渲染,因此对于同一个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):

const routes =  [
    {
      path: '/index',
      components: {
        default: Foo,  //组件Foo渲染在默认视图
        a: Bar,  // 组伯Bar渲染在name='a'的视图中
        b: Baz
      }
    },
    {
      // 没有配置多个components的情况下,只渲染在默认视图中
      path: '/category',
      component: Category   
    }
  ]

嵌套命名视图

我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件

const Index = { 
      template: `
      <div class="index">
        11111 
        <hr/>
          <router-view></router-view>
        <hr/>
        222222
          <router-view name="a"></router-view>
      </div>
        ` 
 }

路由配置

const routes = [
      { path: '/', redirect: '/index' },
      {
        path: '/index', 
        component: Index, 
        children: [
          {
              path: 'child1', 
              components: {
            	default: IndexChild1,  //嵌套命名视图组件
            	a: IndexChild3 // //嵌套命名视图组件
          	  }
          },
          {	
              path: 'child2', 
              component: IndexChild2
          },
        ]
      },
      { path: '/category', component: Category },
      { path: '/discover', component: Discover },
      { path: '/cart', component: Cart },
      { path: '/user', component: User },
]

8. r o u t e 和 route和 routerouter的区别(重要)

在一个vue组件中,都可以访问到这两个对象,它俩的区别 是:

  • this.$route是路由记录(信息)对象,只读,存储了与路由相关的信息

    fullPath: "/index/recommend"
    matched: (2) [{…}, {…}]    //存储了所有级别路由的信息  (如果有两个,则matched[0]是一级路由信息,matched[1]是嵌套路由信息)
    meta: {title: '首页-推荐'}
    name: "recommend"  //在路由配置中给路由命的名字
    params: {}
    path: "/index/recommend"
    query: {}
    
  • this.$router是路由对象,可以用来进行路由跳转

9. 路由的模式

  • 路由模式常见的有hash和history

    // 改变模式,添加mode选项,默认是hash
    
        const router = new VueRouter({
            routes,
            mode: 'history'
        })
    
  • vue-router的hash和history的区别

    hash: 地址栏中有#

    history: 地址栏没有#,更好看一些

  • 原理

    hash: 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

    history: 如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

    ********************但这种模式以后上线,需要后端在服务器上配置才能使用

10. 路由激活时类名的处理

const router = new VueRouter({
  mode: 'history',
  base:  process.env.BASE_URL,  //路由基本站点根目录 
  routes,
  
  // 定义链接激活时的类名
  linkActiveClass: 'active'
})

效果: 当前激活状态的会自动添加active这个类名

11. 路由元信息

携带数据

  • 定义路由元信息

    const routes = [
      {
        path: '/circle',
        component: circle
      },
      {
        path: '/cart',
        component: cart,
        meta: {
          // Authorization 授权
          auth: true
        }
      },
      {
        name: 'my',
        path: '/my',
        component: my,
        // 路由元信息,可以在组件中通过this.$route.meta访问到这些信息
        meta: {
          title: '个人信息',
          icon: 'icon-center',
          auth: true
        }
      },
      {
        path: '/login',
        component: login
      }
    ]
    

12. 导航守卫

又称为路由守卫或路由拦截

重点学习全局前置守卫,其它了解即可

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

全局路由守卫在路由配置文件中定义,并且必须在new VueRouter后定义

单个路由独享的守卫,也是在路由配置文件中定义,但是,是在某一个具体的路由定义中添加

组件级的路由守卫: 添加在某个组件内部

  • 全局前置守卫

    router.beforeEach((to,from,next)=>{
    	
    })    
    
  • 全局解析守卫

    和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

router.beforeResolve((to,from,next)=>{

})     
  • 全局后置钩子

    和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
    
router.afterEach((to,from)=>{

})  
  • 路由独享的守卫(只有一个)

    在路由配置上直接定义 beforeEnter 守卫

{
    path: '/foo',
    component: Foo,
    beforeEnter: (to, from, next) => {
    	// ...
    }
}
  • 组件内的守卫

    const Foo = {
        template: `...`,
        beforeRouteEnter(to, from, next) {
            // 在渲染该组件的对应路由被 confirm 前调用
            // 不!能!获取组件实例 `this`
            // 因为当守卫执行前,组件实例还没被创建
            
            // next的回调会在路由全部解析完毕并且dom更新后执行
            // 创建好的组件实例会作为回调函数的参数传入。
            next(vm=>{
            	console.log('beforeRouterEnter中next的回调',vm.msg)
            })
        },
        beforeRouteUpdate(to, from, next) {
            // 在当前路由改变,但是该组件被复用时调用
            // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
            // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
            // 可以访问组件实例 `this`
        },
        beforeRouteLeave(to, from, next) {
            // 导航离开该组件的对应路由时调用
            // 可以访问组件实例 `this`
        }
    }
    

13. 完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

14. 路由懒加载和项目打包

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

  • 实现方式

    不需要使用import提前引入路由组件

    在路由配置中实现懒加载

    {
        path: '/index',
        // 路由懒加载
        component: ()=> import ('@/views/index.vue'),
        //下面的方式可以给对应的代码块命名
         component: ()=> import (/* webpackChunkName: "index-module" */ '@/views/index.vue'),
     }
    
  • 项目打包

    npm run build
    

    如果没有路由懒加载,会打包成两个js

    app.js: 存储自定义的业务逻辑代码

    chunk-vendor.js: 存储第三方依赖包的代码 如: vue.js vue-router.js

    路由懒加载之后, 懒加载的组件会生成独立的css和js, 并且在访问页面时,会按需加载

15. 404页面的配置

如果用户访问的路由在路由表中没有匹配路径,则应该显示404页面

实现方式: 在所有路由表的最后,添加以下面的配置

{
    // *表示所有路由,如果在上面没有匹配到,就会执行该路由,显示404页面
    // 这个配置必须放在所有路由的最下面
    path: '*',
    component: ()=> import ('@/views/NotFound.vue'),
}

16. 滚动行为

应用场景: 首页和分类页都有滚动效果,如果在首页中页面滚动200px,切换到分类页时,看不到顶部信息,因为页面还在200px偏移的位置

解决方案:

const router = new VueRouter({
  routes,
  //滚动行为,切换路由时页面滚动到顶部
  scrollBehavior(){
    return {
      x: 0, y: 0
    }
  }
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值