vue学习(三)---vue-router路由

1.路由基本结构
2.router-link
3.命名路由
4.路由参数规则
5.重定向和别名
6.$route 和 $router的区别
7.多视图
8.监听路由
9.导航守卫
10. 路由懒加载

路由基本结构

1.容器

 <router-view></router-view>

2.路由表

  let router=new VueRouter({
    routes: [
      {path, component},
      {path, component},
      {path, component},
      ...
    ]
  });

3.添加到vm对象

new Vue({
    el, data, ...,
    router: router
  })


router-link

编译完之后就是a标签。主要通过to属性来进行路由跳转

 <router-link class="nav" :to="{name: 'news', params: {id: 98}}">页面1</router-link>
 <router-link class="nav" to="/b">页面2</router-link>
 <router-link class="nav" to="/c" tag="div">页面3</router-link>

tag可以将默认的a标签改为你指定的标签,比如div

router-link-activerouter-link当前的选中自带class名称,自己可以通过这个class改变成你想要的效果。

router-link 也是遵守下面的路由参数规则



命名路由

对路由设置name属性,为了方便路由的跳转,如果单纯的通过path跳转,一旦path的值过长,或者路由嵌套很深,会显的很乱维护也比较麻烦。
name属性是可选的。

<router-link class="nav" :to="{name: 'news'}">页面1</router-link>


    routes: [
      {
        path: '/news',
        name: 'news', // look at here
        component: {
          template: '<div>新闻:{{$route.params.id}}</div>'
        }
      }
命名路由跳转
//常规
<router-link to="/xxx/xxx">
//命名路由跳转
<router-link class="nav" :to="{name: 'news', params: {id: 98}}">页面1</router-link>
路由可以重叠

当多个路由同时匹配到了,那么谁写在最前面就匹配谁的。

 routes: [
      {
        path: '/news/aaa/',
        component: {
          template: '<div>新闻2</div>'
        }
      },
      {
        path: '/news/:id/',
        component: {
          template: '<div>新闻:{{$route.params.id}}</div>'
        }
      }

如果路由输入为/news/aaa 上面的结果会匹配第一个 显示为新闻2。



路由参数规则

路由可以通过name,path,params,query来进行参数的传递以及路由的跳转。那么应该如何合理的使用这么参数呢?

// 字符串
router.push('home')

// 对象
router.push({ path: '/home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' }})

如果提供了 pathparams 会被忽略(因为path是死路经,params是动态路径,query只是路径后的参数),上述例子中的 query 并不属于这种情况。

所以一般我们写路由的时候可以通过两种方式传参:

  1. router.push({ path: ‘/register’, query: { plan: ‘private’ }}) (path +query) //register?plan=private
  2. router.push({ name: ‘user’, params: { userId: ‘123’ }}) (name+params)// user/123



重定向和别名
重定向

重定向也是通过 routes 配置来完成,下面例子是从 /a 重定向到 /b:

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})

重定向的目标也可以是一个命名的路由:

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

甚至是一个方法,动态返回重定向目标:

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目标路由 作为参数
      // return 重定向的 字符串路径/路径对象
    }}
  ]
})

注意导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。在下面这个例子中,为 /a 路由添加一个 beforeEachbeforeLeave 守卫并不会有任何效果。

别名

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

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

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。



$route 和 $router的区别
当前路由信息:$route

$route.path :字符串,等于当前路由对象的路径,会被解析为绝对路径,如 “/home/news” 。
$route.params :对象,包含路由中的动态片段和全匹配片段的键值对。
$route.query :对象,包含路由中查询参数的键值对。例如,对于 /home/news/detail/01?favorite=yes ,会得到$route.query.favorite = ‘yes’ 。

$route.router :路由规则所属的路由器(以及其所属的组件)。
$route.matched :数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
$route.name :当前路径的名字,如果没有使用具名路径,则名字为空。
在这里插入图片描述


操作路由:$router

this.$router.push( string|object);

fn1(){
        this.$router.push('/news/19'); string
        this.$router.replace({name: 'news', params: {id: Math.random()}}); object
      },

history其实是一个栈,所以路由需要push/replace来操作这个栈。

push(string|object) 入栈

replace(string|object) 替换最后一个历史纪录(当前)

go(int) 就是前进后退



多视图
 <div id="div1">
      <router-link to="/">首页</router-link>
      <router-link to="/news">新闻</router-link>
      <!--1.路由容器-->
      <router-view name="header"></router-view>
      <router-view></router-view>
      <router-view name="footer"></router-view>
    </div>

//components 多个s
let router=new VueRouter({
    routes: [
      {
        path: '/',
        name: 'index',
        components: {
          default: indexCmp,
          header: headerCmp,
          footer: footerCmp
        }
      },
      {
        path: '/news',
        name: 'news',
        components: {
          default: newsCmp,
          header: headerCmp,
          footer: footerCmp
        }
      }
    ]
  });



监听路由

1.watch 简单——只能看不能干预

watch: {
      $route(value, old_value){
        console.log(value, old_value);
      }
    }

2.路由守卫 ---- 可以阻止路由的跳转 也能控制。



导航守卫
1. 全局守卫
2. 单个路由守卫
3. 组件内守卫

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

记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

全局前置守卫

你可以使用 router.beforeEach 注册一个全局前置守卫:

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。

每个守卫方法接收三个参数:

to: Route: 即将要进入的目标 路由对象

from: Route: 当前导航正要离开的路由

next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

  • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。

  • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

  • next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。

  • next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

确保要调用 next 方法,否则钩子就不会被 resolved。

全局后置钩子

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
  // ...
})
路由独享的守卫

你可以在路由配置上直接定义 beforeEnter 守卫:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

这些守卫与全局前置守卫的方法参数是一样的。

组件内的守卫

最后,你可以在路由组件内直接定义以下路由导航守卫:

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

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

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdatebeforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}

这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}
完整的导航解析流程
  1. 导航被触发。
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
整合所有的守卫:

全局的前置守卫: beforeEach beforeResolve
全局的后置钩子: afterEach (钩子函数 这里没有 next
路由独享的守卫: beforeEnter
组件内的守卫: beforeRouterEnterbeforeRouterUpdatebeforeRouteLeave



路由懒加载

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

结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

首先,可以将异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件本身):

  const Foo = () => Promise.resolve({ /* 组件定义对象 */ })

第二,在 Webpack 2 中,我们可以使用动态 import语法来定义代码分块点 (split point)

import('./Foo.vue') // 返回 Promise

如果您使用的是 Babel,你将需要添加 syntax-dynamic-import 插件,才能使 Babel 可以正确地解析语法。

结合这两者,这就是如何定义一个能够被 Webpack 自动代码分割的异步组件。

const Foo = () => import('./Foo.vue')

在路由配置中什么都不需要改变,只需要像往常一样使用 Foo:

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

可在路由中简写
{
path:'/foo',
name:'foo',
component: () => import('@/components/foo')
}
把组件按组分块

有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。


const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

/* webpackChunkName: “group-foo” */ 是打包后文件名称,后面是文件路径。

‘./Foo.vue’ 是文件路径。

(可配置或者不配置)在build目录下找到webpack.prod.conf.js文件,将output修改为

 output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),//文件格式,文件名.文件哈希
    chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')//文件切割后的文件名称。这里的name对应的就是路由中引入文件时候的webpackChunkName
}

还有一种形式:
在这里插入图片描述
也是实现懒加载的方法。

vue-router相关的内容就先介绍到这里了,希望对您有所帮助~。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值