Javascript

Vue--Router篇

本文主要是介绍Vue--Router篇,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1. 什么是前端路由

Hash地址(锚链接#)与组件之间的对应关系

<a href="#a"></a>

<div id="a"></div>

  • Hash地址中#往后的部分就是hash地址
    http://localhost:8080/#/Home
  • Hash地址中/往后的参数项,叫做路径参数
    http://localhost:8080/#/Home

location.hash
location.href

路由占位符
<router-view></router-view>

2. 前端路由的工作方式

  1. 用户点击页面上的路由链接
  2. 导致了URL地址栏上的Hash值发生了变化
  3. 前端路由监听到了Hash地址的变化
  4. 前端路由把当前Hash地址对应的组件渲染到浏览器中

3. 简易路由

//App.vue
<template>

 <div id="app">

 <div id="nav">

 <router-link to="/">Home</router-link> |

 <router-link to="/about">About</router-link>

 </div>

 <router-view/>

 </div>

</template>

// router-index.js
import Vue from 'vue'

import VueRouter from 'vue-router'

import Home from '../views/Home.vue'

  
Vue.use(VueRouter)

  
//创建路由的实例对象
const routes = [
//路由规则

 {

 path: '/',

 name: 'Home',

 component: Home

 },

 {

 path: '/about',

 name: 'About',

 // route level code-splitting

 // this generates a separate chunk (about.[hash].js) for this route

 // which is lazy-loaded when the route is visited.

 component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')

 }

]


const router = new VueRouter({

 routes

})

  

export default router

4. 路由的重定向

  • 用户在访问地址A的时候,强制用户跳转到地址B,从而展示特定的组件页面。
  • 通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由的重定向
  1. 重定向也是通过 routes 配置来完成,下面例子是从 /a 重定向到 /b
//router-index.js
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})
  1. 重定向的目标也可以是一个命名的路由:
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})
  1. 甚至是一个方法,动态返回重定向目标:
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目标路由 作为参数
      // return 重定向的 字符串路径/路径对象
    }}
  ]
})

5. 嵌套路由

官方地址:https://router.vuejs.org/zh/guide/essentials/nested-routes.html

通过路由实现组件的嵌套展示,叫做嵌套路由

  • 实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如:
/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+
  • 通过children属性声明子路由规则
    在src/router/index.js中导入需要的组件,并使用children属性声明子路由规则:
import UserProfile from './components/'
import UserPosts from './components/'

const router = new VueRouter({
  routes: [
    { //父级路由规则
      path: '/user',
      component: User,
	  //子级路由规则
      children: [ 
        {
          // 当 /user/:id/profile 匹配成功,
          // UserProfile 会被渲染在 User 的 <router-view> 中
		  //访问user/profile,展示UserProfile组件
          path: 'profile',
          component: UserProfile
        },
        {
          // 当 /user/:id/posts 匹配成功
          // UserPosts 会被渲染在 User 的 <router-view> 中
		  //访问user/posts,展示UserPosts组件
          path: 'posts',
          component: UserPosts
        }
      ]//子路由结束
    }
  ]//父路由结束
})

tip=>默认子路由 如果children数组中,某个路由规则的path值为空字符串,则这条路由规则,叫做默认子路由

6. 动态路由

把Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性。
在vue-router中使用英文冒号(:)来定义路由的参数项

this.$route是路由的参数对象
this.$router是路由的导航对象

//router/index.js
const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})
//User.vue
//路由ID
const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
  • 当router/index.js的routes添加props:true ,可以传值
routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User,props:true }
  ]
//User.vue
<div>User {{ id }}</div

props:['id']

注意1:

  • Hash地址中/往后的参数项,叫做路径参数
    http://localhost:8080/#/Home
  • this.$route.params来访问路径参数(User)

注意2:

  • Hash地址中?往后的参数项,叫做查询参数
    http://localhost:8080/#/Home/?name=by age=20
  • this.$route.query来访问查询参数

注意3:

  • 在this.$route中,path只是路径部分,fullpath是完整的路径

7. 声明式导航

在浏览器中,点击链接实现导航的方式,叫做声明式导航。
如:普通网页中点击<a>链接、vue项目中点击<router-link>都属于声明式导航

8.编程式导航

在浏览器中,调用API方法实现导航的方式,叫编程式导航。
如:普通网页中调用location.href跳转到新页面的方式,属于编程式导航

tip:在行内使用编程式导航时,this必须要省略,否则会报错

  1. router.push(location, onComplete?, onAbort?)
    注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push
  • 想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

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

<button @click="gotoLogin">跳转到Home/Login</button>


methods:{
	gotoLogin(){
	//通过编程式API跳转页面
		this.$router.push('/home/login')
	}
}
  1. router.replace(location, onComplete?, onAbort?)
  • router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
<button @click="gotoLogin">跳转到Home/Login</button>


methods:{
	gotoLogin(){
	//通过编程式API跳转页面
		this.$router.replace('/home/login')
	}
}
  1. router.go(n)
  • 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

this.$router.go(-1)
  • $router.back()
    在历史记录中,后退到上一个页面

  • $router.forward()
    在历史记录中,前进到下一个页面

9. 导航守卫

可以控制路由的访问权限

9.1 全局前置守卫

每次发生路由的导航跳转时,都会触发全局前置守卫。因此,在全局前置守卫中,程序员可以对每个路由进行访问权限的控制。

//创建路由实例对象
const router = new VueRouter({ ... })

//调用路由实例对象的beforeEach方法,即可声明全局前置守卫
//每次发生路由导航跳转的时候,就会自动触发回调函数
router.beforeEach((to, from, next) => {
  //next()函数表示放行的意思。
  // next() 
})

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

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

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

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

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

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

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

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

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

router.beforeEach((to, from, next) => {
  if (to.path === '/main'){
  	const token = localstorage.getItem('token')
	if(token){
	//访问的是后台主页,且有token的值
	next()
	}else{
	//访问的是后台主页,但没有token的值
		next('/login')
	}
  }
  else{
  	next()//访问的不是后台主页,直接放行
  }
})

9.2 全局解析守卫

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

9.3 全局后置钩子

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

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

9.4 路由独享守卫

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

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

9.5 组件内守卫

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

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建

 	next(vm => {
    // 通过 `vm` 访问组件实例
  	})
  },
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}
这篇关于Vue--Router篇的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!