vue-router (路由)

vue-router

1.安装 vue-router

npm install --save vue-router

2.使用 vue-router

// 1、先引入 vue 和 vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
import Page1 from '../views/page1.vue'

// 2、使用VueRouter插件
Vue.use(VueRouter)
// 3、配置路由规则  [{},{},{}]
const routes = [
  {
    path: '/page1',
    component: Page1
  }
]
// 4、实例化路由器对象,并且使用上面routes规则
const router = new VueRouter({
  routes
})
// 5、将第四步的router暴露出去
export default router
  1. 在 new Vue 实例的地方引入暴露出来的 router 实例对象配置给跟组件的 router 选项
  2. 项目中选择某个位置放入一个 router-view 这个组件 ( 路由视图 ,和slot用法差不多)

router-link 和 a 标签的区别

1、默认情况下,router-link 的 to 属性不需要加 # 号,a标签需要。
2、router-link 可以帮我们实现高亮的效果,通过 class为router-link-active设置样式。router-link-active类名是可以修改的,在router-link标签上设置active-class修改。

动态路由匹配

{
    // 通过 :来指定后面的id是动态路由参数
    path: '/detail/:id/:name',
    component: Detail
 }

当我们使用上路由之后,会在 Vue 的原型上挂载 两个属性

  • ==route== 当前匹配的路由对象信息 使用 this.route可以获取到当前路由对象信息,里面的 params 有传递的动态参数,query是url地址后面?传递的。
  • ==$router== 路由器的实例对象,里面有一些方法

嵌套路由

要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置:

const routes = [
  {
    path: '/home',
    component: Home,
    children: [
      {
        // url地址: /home/page1
        path: 'page1',
        component: Page1
      },
      {
        path: 'page2',
        component: Page2
      }
    ]
  }
 ]

要注意,以 / 开头的嵌套路径会被当作根路径。设置的嵌套路由就无效了。

编程式导航 - 通过js代码来控制路由的跳转

  • $router.push() 跳转页面,新增一个历史记录
  • $router.back() 后退
  • $router.forward() 前进
  • $router.go() 根据参数来看是前进还是后退
  • $router.replace() 重定向页面,不加历史记录
    router-link标签也可以加上replace属性,使其重定向页面,没有历史记录

命令路由

在路由规则上给每个规则加上name属性,后续方便我们操作路由的跳转。一般不会给有子集路由的起名字,只给其子路由命名。

<router-link to="/home/page1"></router-link>
<router-link :to="{ path: '/home/page1', name: 'page1', query: {}, params: {} }"></router-link>

to属性传对象的时候,可以有如果属性

  • path 路由路径
  • name 命名路由的名字
  • query search参数,url ?后面的参数
  • params 动态路由匹配参数

PS: params 与 path 不能共存,如果你要传递 params,那么不要使用 path。path是url地址,params是url地址后面/传递过去的,所以有冲突,会以path为主。

命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s)

重定向和别名

重定向: redirect

“重定向”的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b

{
    // 当url地址都没有匹配到上面的规则的时候,就会匹配*,让url重定向到了 /home/page1
    path: '*',
    redirect: '/home/page1'
}
{
    // 加上这个之后,访问localhost:8080/home 会自动重定向到 /home/page1
    path: '',
    redirect: '/home/page1'
}

别名:alias
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。

{
    name: 'login',
    alias: '/haha', // 定义了一个别名,当地址为haha也能跳转到login页面
    path: '/login',
    component: Login
}

路由组件传参

有三种方法:

1、布尔模式,设置props属性为true

{
    // 通过 :来指定后面的id是动态路由参数
    name: 'detail',
    path: '/detail/:id/:name',
    component: Detail,
    // 设置props为true,在Detial组件中就可以使用 props  
    // 来定义id与name,并且使用props接收并使用id和name,
    // 就不需要使用this.$route.params.id 获取了。
    props: true
}

2、对象模式

props: { id :1, name : '苹果' }

props传一个对象过去,也可以接收到数据。

3、函数模式

props: (route) => {
    return {
        id : route.params.id,
        name : route.params.name
    }
}

vue 路由的两种模式

  • hash (默认),带#号
  • history 不带#号

要修改当前路由模式可以在 实例化 路由器对象的时候设置 mode 选项

new VueRouter({
  mode: 'history'
})

这两种模式的区别

  1. 从外观上来说,hash模式会在url地址上面有一个 # 号,而 history 没有,更像url地址。
  2. 从原理上来说,hash模式是通过 window.onHashChagne 这个事件来处理的。而 history 模式是基于 html5 中 history 新增的一些api. hisotry.pushState() history.replaceState() window.onpopstate 来实现的,window.popstate点击浏览器的前进和后退按钮可以触发。
  3. hisotry模式还需要后台配置去处理上线的404的问题,上线如果不处理,默认是访问dist里面的地址,会自动跳转到首页,但是如果一刷新,就是访问http://localhost:8080/home/page1,而dist中没有哦home文件夹,就会报404,找不到文件。

vue 导航守卫

主要分为三个大块

  • 全局
    • 全局前置 beforeEach
    • 全局解析守卫 beforeResolve ,一般很少用到
    • 全局后置 afterEach
  • 路由独享的
    • beforeEnter 进入当前路由时
  • 组件级别的
    • beforeRouteEnter 进入当前组件时
    • beforeRouteUpdate 当前组件更新时
    • beforeRouteLeave 退出当前组件时

全局前置守卫(beforeEach)

接收一个函数,函数中有三个参数:to,form,next,分别代表要去的路由,来自哪个路由,是否让它去。

  • next:
  • 1、如果直接调用,那么就相当于放行。
  • 2、如果调用,但是传递了一个false,就是不放行。
  • 3、如果不调用,也是不放行。
  • 4、调用并且里面可以传递路由的path路径或者是路由的对象信息。那么就重定向到我们的参数所指定的url地址。一般不会直接传递url地址,传地址会造成死循环,从index去detail,去detail又会触发beforeEach,又去到detail。

nprogress进度条插件可以配合全局前置守卫和全局后置守卫实现进度条的效果。

导航守卫的钩子函数

在路由发生变化的时候会主动触发的一些函数

作用场景
  1. beforeEach 与 afterEach 能实现页面进度条的效果
  2. 登录拦截
    1、 先排除 组件级别
    2、 afterEach 排除
    3、正常情况下,如果是后台管理系统的话,因为处理登录与注册页面之外其他的都需要做登录的拦截,那么就可以再 全局前置 里面去做。如果项目中只有那么一个到两个需要做拦截的页面,那么就可以再他们自己的路由独享里面去做。

使用beforeEach做路由拦截

router.beforeEach((to,from,next) =>{
  NProgress.start()
  // 路由拦截
  // 判断是否去卖座卡页面或者余额页面

  if ( to.path === '/card' || to.path === '/money' ){
    // 判断是否有登陆
    if ( window.localStorage.getItem('userInfo')) {
      // 登陆了,让它去
      next()
    }else{
      // 没登陆,跳去登陆页面
      // next('/login')
      // 传参数过去,知道是想去哪里点击的登陆
      next({
        path: '/login',
        query: {
          // redirect: to.path  // 想去哪个页面,通过query传递过去,或者name和params传递
          // 通过to.path获取到想去的页面,如果带有参数,to.path是不能传递参数过去的。
          redirect: to.fullPath // to.fullPath 能拿到传递的参数(url?后面的参数)
        }
      })
    }
  }else{
    next();
  }
})

login页面可以接受并作出相应的跳转

    // 接收传递过来想去的页面地址
    // let toPage = this.$route.query.redirect; 
    //如果用户直接通过login页面登陆,没传递参数,就让他跳转到个人中心页面
    let toPage = this.$route.query.redirect || '/center'; 
    this.$router.replace(toPage)

一般使用多个页面需要拦截使用beforeEach来做路由拦截,一两个用brforeEnter路由独享做拦截,路由独享做拦截会使代码比较臃肿,因为拦截的代码大致一样。

路由元信息

定义路由的时候可以配置 meta 字段,就可以知道这个路由需要拦截。

{
  path: '/money',
  component: Money,
  name: 'money',
  meta: {
    requireLogin: true
  }
}

下面判断只需要判断meta就可以了

router.beforeEach((to,from,next) =>{
    if(to.meta.requireLogin){
    }else{
        next();
    }
}

动态路由匹配

当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。

复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:

watch: {
    $route (newVal,oldVal) {
      this.getGoods()
    }
  }

或者使用 beforeRouteUpdate(当前路由更新是)的导航守卫:

beforeRouteUpdate (to,from,next) {
    console.log('当前组件更新')
    let newId = to.params.id;
     // 更新进入之后,还没next,url地址还没变,所以要从to里面拿到去哪个地址新的id
     this.getGoods(newId);
    next()
  }

路由的懒加载

需要哪个组件就加载哪个组件。

routes: [
    {
      path: '/',
      // 可以在文件路径前加上/* webpackChunkName: "group-foo" */设置network请求的js名字
      component: ()=> import(/* webpackChunkName: "index" */'../views/index/index.vue'),
      children: [
        {
          path: 'home',
          component: ()=> import('../views/index/home.vue'),
        }
    }
]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容