Vue的路由及路由钩子函数的实现


Posted in Javascript onJuly 02, 2019

什么是路由

什么是路由?网络原理中,路由指的是根据上一接口的数据包中的IP地址,查询路由表转发到另一个接口,它决定的是一个端到端的网络路径。

web中,路由的概念也是类似,根据URL来将请求分配到指定的一个'端'。(即根据网址找到能处理这个URL的程序或模块)
使用vue.js构建项目,vue.js本身就可以通过组合组件来组成应用程序;当引入vue-router后,我们需要处理的是将组件(components)映射到路由(routes),然后在需要的地方进行使用渲染。

其所包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

1、基础路由

当我们通过 vue create 创建项目的的时候,会选择是否安装vue-router,项目创建后,在主组件App.vue中的HTML部分:

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
 <h1>Hello App!</h1>
 <p>
  <!-- 使用 router-link 组件来导航. -->
  <!-- 通过传入 `to` 属性指定链接. -->
  <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
  <router-link to="/foo">Go to Foo</router-link>
  <router-link to="/bar">Go to Bar</router-link>
 </p>
 <!-- 路由出口 -->
 <!-- 路由匹配到的组件将渲染在这里 -->
 <router-view></router-view>
</div>

上述代码中,<router-view/>是路由出口,路由匹配到的组件将渲染在这里。

2、在router/index.js文件中

// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }

// 2. 定义路由每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。

const routes = [
 { path: '/foo', component: Foo },
 
]

// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
 routes 
})

// 4. 创建和挂载根实例。通过 router 配置参数注入路由,从而让整个应用都有路由功能
const app = new Vue({
 router
}).$mount('#app')

3、动态路由

什么是动态路由?动态路由是指路由器能够自动的建立自己的路由表,并且能够根据实际情况的变化实时地进行调整。

1、在vue项目中,使用vue-router如果进行不传递参数的路由模式,则称为静态路由;如果能够传递参数,对应的路由数量是不确定的,此时的路由称为动态路由。动态路由,是以冒号为开头的(:),例子如下:

export default new Router({
 routes: [
  {
   path: '/',
   name: 'HelloWorld',
   component: HelloWorld
  }, {
   path: '/RouterComponents/:id',
   name: 'RouterComponents',
   component: RouterComponents
  }
 ]
})

一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。

2、路由跳转,执行方式有两大类;

第一大类:router-link模式,直接把参数写在to属性里面:

<router-link :to="{name:'RouterComponents',params:{id:110}}">跳转</router-link>

第二大类:$router.push()模式,代码如下:

methods: {
  changeFuc (val) {
   this.$router.push({
    name: 'RouterComponents',
    params: {id: val}
   })
  }
}

或者:

methods: {
  changeFuc (val) {
   this.$router.push({
    path: `/RouterComponents/${val}`,
   })
  }
}

4、路由嵌套

vue项目中,界面通常由多个嵌套的组件构成;同理,URL中的动态路由也可以按照某种结构对应嵌套的各层组件:

const router = new VueRouter({
 routes: [
  { path: '/user/:id', component: User,
   children: [
    {
     // 当 /user/:id/profile 匹配成功,
     // UserProfile 会被渲染在 User 的 <router-view> 中
     path: 'profile',
     component: UserProfile
    },
    {
     // 当 /user/:id/posts 匹配成功
     // UserPosts 会被渲染在 User 的 <router-view> 中
     path: 'posts',
     component: UserPosts
    }
   ]
  }
 ]
})

5、捕获所有路由或404 NotFound路由

常规参数只会匹配被 / 分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):

{
 // 会匹配所有路径
 path: '*'
}
{
 // 会匹配以 `/user-` 开头的任意路径
 path: '/user-*'
}

当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: '*' } 通常用于客户端 404 错误。如果你使用了History 模式,请确保正确配置你的服务器。

6、编程式导航

声明式 编程式
router.push(...)

想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)。

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

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

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

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

如果提供了 path,params 会被忽略

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

7、命名路由

由于我们需要通过不同的路由跳转到不同的页面,这时给我们的路由都加一个名字操作起来会比较方便

const router = new VueRouter({
 routes: [
  {
   path: '/user/:userId',
   name: 'user',
   component: User
  }
 ]
})
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

8、命名视图

有时候我们需要一个布局,这时候,我们就需要用到命名视图。

<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>
const router = new VueRouter({
 routes: [
  {
   path: '/',
   components: {
    default: Foo,
    a: Bar,
    b: Baz
   }
  }
 ]
})

9、嵌套命名视图

{
 path: '/settings',
 // 你也可以在顶级路由就配置命名视图
 component: UserSettings,
 children: [{
  path: 'emails',
  component: UserEmailsSubscriptions
 }, {
  path: 'profile',
  components: {
   default: UserProfile,
   helper: UserProfilePreview
  }
 }]
}

10、路由组件传参

在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。

使用 props 将组件和路由解耦:

取代与 $route 的耦合

const User = {
 template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
 routes: [
  { path: '/user/:id', component: User }
 ]
})

通过 props 解耦

const User = {
 props: ['id'],
 template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
 routes: [
  { path: '/user/:id', component: User, props: true },

  // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
  {
   path: '/user/:id',
   components: { default: User, sidebar: Sidebar },
   props: { default: true, sidebar: false }
  }
 ]
})

路由钩子

1、路由钩子

在某些情况下,当路由跳转前或跳转后、进入、离开某一个路由前、后,需要做某些操作,就可以使用路由钩子来监听路由的变化

全局路由钩子:router.beforeEach 注册一个全局前置守卫

router.beforeEach((to, from, next) => {
  //会在任意路由跳转前执行,next一定要记着执行,不然路由不能跳转了
 console.log('beforeEach')
 console.log(to,from)
 //
 next()
})
//
router.afterEach((to, from) => {
  //会在任意路由跳转后执行
 console.log('afterEach')
})

单个路由钩子:

只有beforeEnter,在进入前执行,to参数就是当前路由

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

路由组件钩子:

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

附:完整的导航解析流程

  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 的回调函数。

2、路由元信息

定义路由的时候可以配置 meta 字段:

const router = new VueRouter({
 routes: [
  {
   path: '/foo',
   component: Foo,
   children: [
    {
     path: 'bar',
     component: Bar,
     // a meta field
     meta: { requiresAuth: true }
    }
   ]
  }
 ]
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 异步调用框架 (Part 1 - 问题 &amp; 场景)
Aug 03 Javascript
jquery与google map api结合使用 控件,监听器
Mar 04 Javascript
JavaScript 一行代码,轻松搞定浮动快捷留言-V2升级版
Apr 02 Javascript
Javascript中valueOf与toString区别浅析
Mar 19 Javascript
jquery实现可拖动DIV自定义保存到数据的实例
Nov 20 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
Apr 06 Javascript
javascript实现类似百度分享功能的方法
Jul 27 Javascript
seajs中最常用的7个功能、配置示例
Oct 10 Javascript
微信小程序实现动态设置页面标题的方法【附源码下载】
Nov 29 Javascript
Vue组件中slot的用法
Jan 30 Javascript
js中let能否完全替代IIFE
Jun 15 Javascript
JavaScript 继承 封装 多态实现及原理详解
Jul 29 Javascript
Node.js 实现远程桌面监控的方法步骤
Jul 02 #Javascript
使用vue中的混入mixin优化表单验证插件问题
Jul 02 #Javascript
vue history 模式打包部署在域名的二级目录的配置指南
Jul 02 #Javascript
简单了解微信小程序的目录结构
Jul 01 #Javascript
vue如何实现自定义底部菜单栏
Jul 01 #Javascript
微信小程序如何利用getCurrentPages进行页面传值
Jul 01 #Javascript
vue中的面包屑导航组件实例代码
Jul 01 #Javascript
You might like
全国FM电台频率大全 - 5 内蒙古自治区
2020/03/11 无线电
php读取javascript设置的cookies的代码
2010/04/12 PHP
PHP Global定义全局变量使用说明
2013/08/15 PHP
yii2.0实现验证用户名与邮箱功能
2015/12/22 PHP
PHP实现数组array转换成xml的方法
2016/07/19 PHP
JS解决url传值出现中文乱码的另类办法
2013/04/08 Javascript
jQuery层次选择器选择元素使用介绍
2013/04/18 Javascript
JS调用CS里的带参方法实例
2013/08/01 Javascript
js中文逗号转英文实现
2014/02/11 Javascript
jquery重复提交请求的原因浅析
2014/05/23 Javascript
AngularJS基础教程之简单介绍
2015/09/27 Javascript
jQuery实现简单的抽奖游戏
2017/05/05 jQuery
JS实现求数组起始项到终止项之和的方法【基于数组扩展函数】
2017/06/13 Javascript
基于js中的原型(全面讲解)
2017/09/19 Javascript
Vue2.0 http请求以及loading展示实例
2018/03/06 Javascript
elementUI table表格动态合并的示例代码
2019/05/15 Javascript
js尾调用优化的实现
2019/05/23 Javascript
JavaScript中变量提升和函数提升的详解
2020/08/07 Javascript
[16:21]教你分分钟做大人:圣堂刺客
2014/12/03 DOTA
跟老齐学Python之有点简约的元组
2014/09/24 Python
python中引用与复制用法实例分析
2015/06/04 Python
深入解析Python的Tornado框架中内置的模板引擎
2016/07/11 Python
numpy添加新的维度:newaxis的方法
2018/08/02 Python
Python 中 function(#) (X)格式 和 (#)在Python3.*中的注意事项
2018/11/30 Python
python+mysql实现学生信息查询系统
2019/02/21 Python
python 字典操作提取key,value的方法
2019/06/26 Python
python字符串查找函数的用法详解
2019/07/08 Python
python读取配置文件方式(ini、yaml、xml)
2020/04/09 Python
Pymysql实现往表中插入数据过程解析
2020/06/02 Python
Keras实现支持masking的Flatten层代码
2020/06/16 Python
Python绘制K线图之可视化神器pyecharts的使用
2021/03/02 Python
《雨点》教学反思
2014/02/12 职场文书
三分钟英语演讲稿
2014/04/24 职场文书
白酒营销策划方案
2014/08/17 职场文书
初婚未育证明样本
2014/10/24 职场文书
安全生产会议制度
2015/08/06 职场文书