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 相关文章推荐
flash 得到自身url参数的代码
Nov 15 Javascript
JavaScript关闭当前页面(窗口)不带任何提示
Mar 26 Javascript
浅谈Javascript中匀速运动的停止条件
Dec 19 Javascript
一道JS前端闭包面试题解析
Dec 25 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
Sep 04 Javascript
Bootstrap分页插件之Bootstrap Paginator实例详解
Oct 15 Javascript
jQuery中 bind的用法简单介绍
Feb 13 Javascript
node.js学习之断言assert的使用示例
Sep 28 Javascript
vue中slot(插槽)的介绍与使用
Nov 12 Javascript
详解Angular模板引用变量及其作用域
Nov 23 Javascript
js实现圆形显示鼠标单击位置
Feb 11 Javascript
微信小程序实现音乐播放页面布局
Dec 11 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
常用表单验证类,有了这个,一般的验证就都齐了。
2006/12/06 PHP
解决phpcms更换javascript的幻灯片代码调用图片问题
2014/12/26 PHP
帝国cms常用标签汇总
2015/07/06 PHP
PHP仿tp实现mvc框架基本设计思路与实现方法分析
2018/05/23 PHP
php+Ajax无刷新验证用户名操作实例详解
2019/03/04 PHP
Thinkphp 在api开发中异常返回依然是html的解决方式
2019/10/16 PHP
use jscript Create a SQL Server database
2007/06/16 Javascript
关于js遍历表格的实例
2013/07/10 Javascript
js如何实现设计模式中的模板方法
2013/07/23 Javascript
jquery中交替点击事件toggle方法的使用示例
2013/12/08 Javascript
JS简单限制textarea内输入字符数量的方法
2015/10/14 Javascript
jquery radio的取值_radio的选中_radio的重置方法
2016/09/20 Javascript
JS中用childNodes获取子元素换行会产生一个子元素
2016/12/08 Javascript
jQuery插件HighCharts绘制2D柱状图、折线图的组合双轴图效果示例【附demo源码下载】
2017/03/09 Javascript
vue-cli如何快速构建vue项目
2017/04/26 Javascript
从零开始实现Vue简单的Toast插件
2018/12/03 Javascript
使用form-create动态生成vue自定义组件和嵌套表单组件
2019/01/18 Javascript
Vue项目页面跳转时浏览器窗口上方显示进度条功能
2020/03/26 Javascript
js里面的变量范围分享
2020/07/18 Javascript
Python 解析XML文件
2009/04/15 Python
python使用cStringIO实现临时内存文件访问的方法
2015/03/26 Python
图文详解WinPE下安装Python
2016/05/17 Python
python matplotlib 在指定的两个点之间连线方法
2018/05/25 Python
python中selenium操作下拉滚动条的几种方法汇总
2019/07/14 Python
Django中密码的加密、验密、解密操作
2019/12/19 Python
DJI大疆无人机官方商城:全球领先的无人飞行器研发和生产商
2016/12/21 全球购物
上海天奕面试题笔试题
2015/04/19 面试题
工商管理专业实习生自我鉴定
2013/09/29 职场文书
服务中心夜班服务员岗位职责
2013/11/27 职场文书
初一生物教学反思
2014/01/18 职场文书
四年级数学教学反思
2014/02/02 职场文书
小学生检讨书大全
2014/02/06 职场文书
大堂副理的岗位职责范文
2014/02/17 职场文书
五一劳动节活动总结
2015/02/09 职场文书
安全主题班会教案
2015/08/12 职场文书
2016年六一文艺汇演开幕词
2016/03/04 职场文书