vue-router的这些易混知识点你都掌握了吗

583 阅读2分钟

这是我参与8月更文挑战的第3天,活动详情查看: 8月更文挑战” 。

1. Vue中router和routes和route的区别

在Vue中,router指向的是大路由,routes是路由配置数组, route指向的是当前活跃的路由。下面我们详细了解一下这三者。

1.1 router:是VueRouter的一个实例对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象。例如$router,它是一个全局路由对象,包含了路由跳转的方法、钩子函数等。在组件内可通过 this.$router 访问整个路由器

在项目中的应用有:

  • router的index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes
})
  • 路由导航守卫router.beforeEach和router.afterEach
router.beforeEach((to, from, next) => {})
  • 关于routerrouter `router`常用于编程式导航中,首先打印一下$router的内容。 image.png
  • this.$router.push方法

    该方法的参数可以是一个字符串,也可以是一个描述地址的对象。

    // 字符串 
    this.$router.push('home') ;
    
    //对象 
    this.$ruter.push({path:'home'}) 
    
    //命名路由 
    this.$router.push({name:'Detail',params:{id:1}}) 
    
    //携带参数
    this.$router.push({
      path: '/product/edit-basic-info',
      query: { from_type: 'add' }
    })
    
  • this.$router.replace方法

    this.$router.pushthis.$router.replace方法很像,写法是一样的,但是实际的效果是不一样的。push是向history里添加新记录,而replace是直接将当前浏览器history记录替换掉。

    • 用push方法,页面A跳转到页面B,使用浏览器的后退可以回到页面A。
    • 用replace方法,页面1被替换成页面B,使用浏览器的后退,就回不到页面A,只能回到页面B的前一页面。 在项目中的应用场景常用于权限验证,验证之后不想让用户回退到之前的页面,比如: 购物车页面需要用户登录,如果用户没有登录即跳转到登录页面,登录之后使用replace回到购物车页面,当然也可以使用router.go(-1)方法回退到上一页面。

1.2 routes:是路由的集合,类型是一个数组,用来配置多个route路由对象。在项目中的应用如下:

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: AccountLogin,
    hidden: true
  },
  {
    path: '/',
    component: Home,
    redirect: '/product/list',
    meta: {
      // pageTitle: 'xxxxx管理系统'
    },
    children: [
      {
        path: '/product/list',
        name: 'ProductManagement',
        component: ProductManagement,
        redirect: '/product/list',
        meta: {
          title: '产品管理',
          icon: 'iconfont icon-chanpinguanli',
          // pageTitle: 'xxxxx管理系统',
          dropDown: true
        }
    ]
  }
]

1.3 route:是路由信息对象,每一个路由都会有一个route对象,是一个局部对象,例如:$route指的就是当前路由对象。route包含path,params,hash,query,fullPath,matched,name等路由信息参数。

image.png 首先简单介绍下常用的路由对象属性,方便之后的应用。在组件内可以通过this.$route(切记切记不是this.$router哦!)进行访问。 \

  • $route.path 类型: string字符串,对应当前路由的路径,总是解析为绝对路径,如 "/shop/layout"
  • $route.params 类型: Object 一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象。
  • $route.query 类型: Object 一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /detail?id=1,则有 this.$route.query.id == 1,如果没有查询参数,则是个空对象。
  • $route .name 类型: string字符串, 当前路由的名称,如果有的话。这里建议最好给每个路由对象命名,方便以后编程式导航使用。特别要注意的是name必须唯一!
  • $route.hash 类型: string 当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
  • $route.fullPath 类型: string 完成解析后的 URL,包含查询参数和 hash 的完整路径。
  • $route.matched 类型: Array<RouteRecord> 一个数组,包含当前路由的所有嵌套路径片段的路由记录。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。$route.redirectedFrom 如果存在重定向,即为重定向来源的路由的名字。

在组件内可通过this.$route 访问 当前路由

this.$route.path
this.$route.query
this.$route.params
this.$route.meta

2. vue-router传参

  • params 参数不会显示在URL地址栏中,当用户刷新页面后,params参数就会被清空。只能使用name,不能使用path。在编程式导航中pathparams是不能同时生效的,使用了path,params就会被忽略掉。所以使用对象写法进行params传参时,可以使用path加冒号:,或者通过name和params进行传参。
// 传递参数
this.$router.push({
    name:'Detail',
    params:{
        id:1
    }
})
this.$router.push({
    path:'/detail',
    params:{id:1} //此时这个params是无效的
})
// 接收参数
let id=this.$route.params.id
  • query 参数会显示在路URl地址栏中,用户刷新页面之后参数也不会丢失,可以使用name,也可以使用path。
// 传递参数
this.$router.push({
    name:'Detail',
    query:{
        id:1
    }
})
this.$router.push({
    path:'/detail:id',
})
this.$router.push({
    path:'/detail',
    query:{
        id:1
    }
})
// 接收参数
let id=this.$route.query.id

3. vue-router响应路由参数的变化

在用动态路由匹配时,例如从/detail/1到detail/2,两个路由都渲染同一个组件,原来的组件实例会被复用,此时如果想在路由改变时做些什么操作,或者想对参数的变化做出响应的话,我们可以通过监听$route来实现这个需求。

  • 用watch监测
watch:{
    $route(to,from){
        console.log(to,from)
        // TODO SOMETHING
    }
}
  • 组件内导航钩子函数
beforeRouteUpdate(to,from,next){
    console.log(to,from,next)
    // TODO SOMETHING
}

4. beforeRouteEnter与this

组件的导航守卫中beforeRouteEnter守卫不能通过this访问组件实例,因为守卫在导航确认前被调用,因此即将登场的新组建还没有被创建。可以通过传一个回调给next来访问组件实例,在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter(to, from, next) {
    next(vm => {
      //vm.fromRoute即this.fromRoute
      vm.fromRoute = from
    })
  }

5. 打开新的窗口

在项目中,我们的应用是一个单页面应用,有时某个页面想要以新窗口的方式打开,我们就可以使用下面的方式实现。

  • 第一种方式
const { href } = this.$router.resolve({
path:'/detail'
query:{id:'1'}
})
window.open(href, '_blank')
  • 第二种方式
<router-link target="_blank" :to="{path:'/detail',query:{id:'1'}}">打开新页面</router-link>
  • 第三种方式
<a :href="`http://${domain}`" target="_black">打开新页面</a>