Vue router($router,$route和守卫)

Vue router传送门
编程式的导航

  • Vue路由
    • 一、spa
      • 什么是spa
      • spa的特点
    • 二、 如何实现单页面效果
      • 区分router
      • router的模式
    • 三、 从安装创建入手
      • HashHistory
      • HTML5History
      • 两种模式比较
    • 四、 路由的使用
      • 路由跳转传参
      • 路由的显示容器
      • 如何获取路由参数
    • 五、 路由的钩子函数
      • 全局前置守卫、全局解析守卫、全局后置守卫
      • 路由的独享守卫
      • 组件内的守卫
      • Vue-router的使用方式

什么是SPA

单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,
是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。

  • SPA的特点
    • 优点
      • 1、用户操作体验好,用户不用刷新页面,整个交互过程都是通过Ajax来操作。
      • 2、适合前后端分离开发,服务端提供http接口,前端请求http接口获取数据,使用JS进行客户端渲染。
    • 缺点:
      * 1、首页加载慢
      单页面应用会将js、 css打包成一个文件,在加载页面显示的时候加载打包文件,如果打包文件较大或者网速慢则用户体验不好,首屏时需要请求一次html,同时还要发送一次js请求,两次请求回来了,首屏才会展示出来。相对于多页应用
      * 2、SEO不友好
      SEO效果差,因为搜索引擎只认识html里的内容,不认识js的内容,而单页应用的内容都是靠js渲染生成出来的,搜索引擎不识别这部分内容,也就不会给一个好的排名,会导致单页应用做出来的网页在百度和谷歌上的排名差。使用单页面应用将大大减少搜索引擎对网站的收录。

为什么页面切换快?

页面每次切换跳转时,并不需要做html文件的请求,这样就节约了很多http发送时延,我们在切换页面的时候速度很快。

有这些缺点,为什么还要使用Vue呢?

Vue还提供了一些其它的技术来解决这些缺点,比如说服务器端渲染技术(我是SSR),通过这些技术可以完美解决这些缺点,解决完这些问题,实际上单页面应用对于前端来说是非常完美的页面开发解决方案。

在这里插入图片描述
如何实现单页面效果 => Router
路由需要满足的功能
从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下):
记录当前页面的状态(保存或分享当前页的url,再次打开该url时,网页还是保存(分享)时的状态)
可以使用浏览器的前进后退功能(如点击后退按钮,可以使页面回到使用ajax更新页面之前的状态,url也回到之前的状态)
要实现这两个功能,我们需要做到:
改变url且不让浏览器向服务器发出请求
监测 url 的变化
截获 url 地址,并解析出需要的信息来匹配路由规则。
区分Router 、Route
Router: 路由器,负责路由的调度、中转
Route: 路由,用于资源通信的载体、类似于路由器上的LAN
路由的模式
• Hash
• 利用URL中的# 资源定位符
• History
• H5新增的pushState、repalceState 方法
//2
单页面应用
1,用户体验好
2,适合前后端分离
缺点:首页加载慢,
不利于seo

路由就是改变应用的路徑

路由有三种模式
history 默认‘/’ 需要浏览器支持—>html5的api运用的事HTML5的API,pushState()和replaceState()对浏览器历史记录栈修改
hash 默认’/#/'兼容性好,window.addEventListen hash change 监听地址栏
#符号本身以及它后面的字符称之为hash,可通过window.location.hash属性读取。它具有如下特点
• hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面
• 可以为hash的改变添加监听事件 window.addEventListener(“hashchange”, funcRef, false)
• 每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录
利用hash的以上特点,就可以来实现前端路由“更新视图但不重新请求页面”
abstract----->服务端 array方式模拟的进栈出栈的方式
添加链接描述

Vue路由$router和$route是什么?区别是什么?

$router为VueRouter的实例,相当于一个全局的路由器对象,里面含有所有的子对象和属性,例如history对象。。。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样。
在这里插入图片描述

以history对象来举例:

$router.push({path:‘home’}),本质是向history栈中添加一个路由,在我们看来是切换路由,但本质是
this.$router.push会往history栈中添加一个新的history记录。
$router.replace({path:‘home’}),//替换路由,没有历史记录【常用于404页面】
详细见vue官方文档

返回上一个历史history用$router.go(-1)

$route是正在跳转的这个路由的局部对象[路由对象,信息对象],里面可以获取当前路由的name,path,query,parmas,hash,fullpath,meta等 可以拿里边的值来做各种判断。在这里插入图片描述
$route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews
$route.params 对象,含路有种的动态片段和全匹配片段的键值对,不会拼接到路由的url后面
$route.query 对象,包含路由中查询参数的键值对。会拼接到路由url后面
$route.router 路由规则所属的路由器
$route.matchd 数组,包含当前匹配的路径中所包含的所有片段所对象的配置参数对象
$route.name 当前路由的名字,如果没有使用具体路径,则名字为空

vue-router传递参数分两大类

  • 1,编程式的导航 router.push

  • 2,声明式的导航<router-link>

  • vue-router传递参数分两大类
    1, 编程式的导航 router.push

    传递参数类型一字符串:字符串的方式是直接将路由地址以字符串的方式来跳转,这种方式很简单但是不能传递参数:

        this.$router.push("home");
    

    传递参数类型二对象:传递参数主要就是以对象的方式来写,分为两种方式:
    1; 命名路由[params]、 2;查询参数[query]。
    命名路由的前提就是在注册路由的地方需要给路由命名如:
    在这里插入图片描述

    命名路由传递参数需要使用params来传递,这里一定要注意使用params不是query。在这里插入图片描述
    目标 页面接收传递参数时使用params
    在这里插入图片描述
    特别注意命名路由这种方式传递的参数,如果在目标页面刷新是会出错的。

    查询参数其实就是在路由地址后面带上参数。
    和传统的url参数一致的,传递参数使用query而且必须配合path来传递参数而不能用name在这里插入图片描述
    目标页面接收传递的参数使用query。this.$route.query.userId
    注意和name配对的是params,和path配对的是query

    • 2,声明式的导航

    声明式的导航也分为两种方式:例子如下:
    1; 命名路由[params]、 2;查询参数[query]。

    字符串

    <router-link to="news">
    	click to news page
    </router-link>
    

    命名路由

    <router-link :to="{ name: 'news', 
    params: { userId: 123}}">
    	click to news page
    </router-link>
    

    查询参数

    <router-link :to="{ path: '/news', 
    query: { userId: 123}}">
    	click to news page
    </router-link>
    

总结:路由传递参数和传统传递参数是一样的,命名路由类似表单提交而查询就是url传递,在vue项目中基本上掌握了这两种传递参数就能应付大部分应用了,最后总结为以下:

  • 1.命名路由搭配params,刷新页面参数会丢失
  • 2.查询参数搭配query,刷新页面数据不会丢失
  • query使用path和name传参跳转都可以,而params只能使用name传参跳转。
  • 3.接受参数使用this.$router后面就是搭配路由的名称就能获取到参数的值

3,动态传参

现有如下场景,点击父组件的li元素跳转到子组件中,并携带参数,便于子组件获取数据。
在这里插入图片描述

	goDescribe(id){
	  this.$router.push({
	    path: `/describe/${id}`,
	  })
	}
需要对应路由配置如下:
   {
     path: '/describe/:id',
     name: 'Describe',
     component:line
   }

很显然,需要在path中添加/:id来对应 $router.push 中path携带的参数。在子组件中可以使用来获取传递的参数值。
在这里插入图片描述

完整的导航解析流程

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

注:“导航”表示路由正在发生改变。
作用:主要用来通过跳转或取消的方式守卫导航。
植入方式:全局的, 单个路由独享的, 或者组件级的。

全局前置守卫:

router.beforeEach

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

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

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

  1. to: Route: 即将要进入的目标 路由对象
  2. from: Route: 当前导航正要离开的路由
  3. 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。

全局解析守卫

在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,
区别是:在导航被确认之前,
同时在所有组件内守卫和异步路由组件被解析之后,
解析守卫就被调用。

全局后置钩子

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

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

路由独享的守卫

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

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

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

组件内的守卫

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

  1. beforeRouteEnter

  2. beforeRouteUpdate (2.2 新增)

  3. 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 传递回调的唯一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来说,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)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值