v-router 路由基础

Posted 小hu同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了v-router 路由基础相关的知识,希望对你有一定的参考价值。

导读:由于本篇文章我是在juejin上面发了后,复制过来的,所以会有一些动态图没有动,图片有水印,排版等问题

一、路由的基本概念与原理

1.什么是路由

路由(英文:router)就是对应关系。

2.SPA 与前端路由

SPA 指的是一个 web 网站只有唯一的一个 html 页面,所有组件的展示与切换都在这唯一的一个页面内完成。
此时,不同组件之间的切换需要通过前端路由来实现。 结论:在 SPA 项目中,不同功能之间的切换,要依赖于前端路由来完成!

3.什么是前端路由

概念:Hash 地址与组件之间的对应关系。

4.前端路由的工作方式

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

5.实现简易的前端路由

前提准备:

创建一个Vue 项目
创建几个.vue组件,并且导入和注册组件,并且使用

// 后面的才代表的是hash地址 ,如果没有# 则不代表hash地址
    <a href="#/home">首页</a>
    <a href="#/move">电影</a>
    <a href="#/about">关于</a>
    
   <!-- 动态组件 -->
   // 动态绑定一个is "comname值",在data中定义默认要展示的是哪个组件
    <component :is="comname"></component>
// 导入组件
import Home from '@/components/Home.vue'
import Movie from '@/components/Movie.vue'
import About from '@/components/About.vue'
export default 
  name: 'App',
  data() 
    return 
      // 在动态组件要展示的名字
      comname:'Home'  
    
  ,
    //created生命周期函数
  created() 
    //只要当前的APP组件被创建,就立即监听widows下面的onhashchange事件  要展示的组件的名字 值必须是字符串 onhashchange 事件
    window.onhashchange = ()=>
      console.log('监听到了hash地址的变化',location.hash);
      //判断hash地址的值 如果等于#/home的值,这comname就改为Home                                                                       
      switch(location.hash)
        case'#/home':
        this.comname = 'Home'
        break
        case'#/move':
        this.comname = 'Movie'
        break
        case'#/about':
        this.comname = 'About'
        break
      
    
  ,
  // 注册组件
  components: 
    Home,
    Movie,
    About
  

可以看到我这里点击了,a链接,改变了hash的值,页面也跟着变化了

二、vue-router 的基本用法

1.什么是 vue-router

vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA(单页面)
项目中组件的切换。

vue-router 的官方文档地址:router.vuejs.org/zh/

2.vue-router 安装和配置的步骤

一般我们在创建项目的时候,可以勾选安装 router插件,会默认的帮我们配置好文件夹及文件

  1. 安装 vue-router 包
  2. 创建路由模块
  3. 导入并挂载路由模块
  4. 声明路由链接和占位符

2.1 安装vue-router 包

npm i vue-router -S 
//使用这个命令默认安装最新版本  加上@***,可指定版本号
// -S 是表示将插件安装到 "dependencies"

2.2 创建路由模块

在 src 源代码目录下,新建 router/index.js 路由模块,并初始化如下的代码:

// 当前项目的路由模块
import Vue from 'vue'
import VueRouter from 'vue-router'

// 将 VueRouter安装为use插件里面
// Vue.use 就是来安装插件的
Vue.use(VueRouter)

// 创建一个router实例对象
const router = new VueRouter()

//向外共享路由的实例对象
export default router

2.3 导入并挂载路由模块

在Vue中使用路由,需要在main.js入口文件导入挂载路由
main.js文件

// 导入路由模块 目的 拿到路由的实例对象
// 在模块化导入的时候 默认的会去找index.js
// import router from '@/router/ 这种导入也是可行的
import router from '@/router/index.js'

new Vue(
  render: h => h(App),
  // 在Vue 项目中 要想吧路由用起来 必须吧路由实例对象 通过下面的方式进行挂载
  // router: 路由的实例对象
  // 名字和属性名是一样的时候 可简写 router
  router: router
).$mount('#app')

2.4 声明路由链接和占位符

App.vue文件

<!-- 当安装和配置了router后 就可以使用 router-link来替代普通的a链接 -->
    <!-- <a href="#/homes">首页</a> -->
    <router-link to="/homes">首页</router-link>
    <router-link to="/Movie">电影</router-link>
    <router-link to="/About">关于</router-link>

  <!-- 只要在项目中配置了vue-router 就可以使用router-view这个组件了 -->
  <!-- 组件渲染到这个里面-->
    <!-- 它的作用很单纯 占位符 -->
    <router-view></router-view>

3.声明路由匹配规则

在 src/router/index.js 路由模块中,通过 routes 数组声明路由的匹配规则。示例代码如下:

// 导入需要的组件
import Home from '@/components/Home.vue'
import Movie from '@/components/Movie.vue'
import About from '@/components/About.vue'

// 创建一个router实例对象
const router = new VueRouter(
  // routes 是一个数组 作用:定义hash 地址与“组件”之间的对应关系
  routes: [
      // 重定向的路由规则
     //当路由访问/为斜杠的hash地址,重定向到/homes组件
     path: '/', redirect: '/homes' ,
    // 路由规则
    //path 代表hash地址 component表示的是组件
     path: '/homes', component: Home ,
     path: '/Movie', component: Movie ,
     path: '/about', component: About 
  ]
  )

三、Vue-router的常见用法

1.路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。通过路由规则的 redirect
属性,指定一个新的路由地址,可以很方便地设置路由的重定向

 path: '/', redirect: '/homes' ,

2.嵌套路由

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

2.1 声明子路由链接和子路由占位符

app.vue

<router-link to="/about">关于</router-link>
//父级占位符
<router-view></router-view>

about.vue

<!-- 子集路由链接 -->
    <router-link to="/about">tab1</router-link>
    <router-link to="/about/tab2">tab2</router-link>
   //子级占位符
   <router-view></router-view>

注意:需要创建两个组件文件,在引入

2.2 通过 children 属性声明子路由规则

路由模块 router/index.js

//导入组件
import Tab1 from '@/components/tabs/Tab1.vue'
import Tab2 from '@/components/tabs/Tab2.vue'

// 创建一个router实例对象
const router = new VueRouter(
  // routes 是一个数组 作用:定义hash 地址与“组件”之间的对应关系
  routes: [
   
      path: '/about',
      component: About,
      //路由重定向
      // redirect: '/about/tab1',
      children: [
        //1、通过children 属性 嵌套声明子级路由规则
        // 子路由规则
        // 默认子路由 如果children 数组中 某个路由规则的path 值 为空字符串
        // 则这条路由规则 叫做“默认子路由”
        // path 不要加 /
         path: '', component: Tab1 ,
         path: 'tab2', component: Tab2 
      ]
    ,
  ]
  )

3.动态路由匹配

看看下面这个

 <!--注意 在hash 地址中 /后面的参数是路径参数  -->
    <!-- 在路由参数对象 需要使用this.$route.params 来访问路径参数 -->
    <!-- 注意2 在hash地址中 ?后面的参数项 叫做 “查询参数” -->
    <!-- 在 路由参数对象中 需要使用this.$route.query来访问查询参数 -->
    
    <!-- 注意3 在this.$route 中 path 只是路径部分 fullPath是完整的hash 地址 -->
    <!-- 例如 -->
    <!-- /movie/2?name=zs%20age%3D12 是完整的fullPath -->
    <!-- /movie/2 是path -->

<router-link to="/movie/1">1</router-link>
<router-link to="/movie/2">2</router-link>
<router-link to="/movie/3">3</router-link>

路由规则

path:'/movie/1',component:Movie
path:'/movie/2',component:Movie
path:'/movie/3',component:Movie

按照上面这种去做的话 代码量会很大,复用性会很低

3.1动态路由的概念

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

 // 在movie 组件中 根据id的值  展示对应电影的详细信息
    // props:true 为路由开启传参 从而方便拿到动态路由参数的值
    //这个id 是自定义名称 和任意定义
 path: '/movie/:id', component: Movie, props: true ,

如何获取到id呢?看下图,可以看到我打印了当前的组件实例,可以看到在$route对象下面有一个 params,里面的id就是id值

我们可以渲染到页面上看看

<!-- this.$route 是路由的参数对象 -->
    <!-- this.$router 是路由的导航对象 -->
    id为props里面接到的id
 <h3>Movie 组件-----this.$route.params.id----id</h3>
 
 代码优化:
 //直接在props里面接一个id
 export default 
  // 接收props 数据传参
  props:[
    'id'
  ],
  

4.声明式导航&编程式导航

在浏览器中,点击链接实现导航的方式,叫做声明式导航。例如:普通网页中点击 <a> 链接、vue 项目中点击 <router-link>
都属于声明式导航
在浏览器中,调用 API 方法实现导航的方式,叫做编程式导航
例如: 普通网页中调用 location.href跳转到新页面的方式,属于编程式导航

4.1 vue-router 中的编程式导航 API

vue-router 提供了许多编程式导航的 API,其中最常用的导航 API 分别是:

1.this.$route.push('hash地址')

跳转到指定的hash地址,并增加1条记录

<button @click="tomovie1">push跳转电影1</button>
 <script>
export default 
  name: 'Home',
  methods: 
    tomovie1()
      // 通过编程式导航API 跳转到指定的hash地址 并增加一条历史记录
      this.$router.push('/movie/1')
      
  ,

</script>

2.this.$route.replace('hash地址')

跳转到指定的 hash 地址,并替换掉当前的历史记录

 <button @click="tomovie2">replace跳转电影2</button>
 <script>
export default 
  name: 'Home',
  methods: 
     tomovie2()
      // 通过编程式导航API 跳转到指定的hash地址  并替换掉当前的历史记录
      this.$router.replace('/movie/2')
    ,
  ,

</script>

3.this.$route.go(数值n)

实现导航历史前进、后退

<button @click="goto">go后退</button>
<script>
export default 
    goto()
      // go(-1)表示后退一层
      // 如果后退的层数超过上限 则原地不动
      this.$router.go(-1)
    
  ,

</script>

4.2 $router.go的简化用法

在实际开发中,一般只会前进和后退一层页面,因此vue-router提供了如下两个便捷方法:

1、$router.back()

在历史记录中,后退到上一个页面

2、$router.forward()

在历史记录中,前进到下一个页面

 <!-- 路由的另一种方式 -->
//在行内使用编程式导航跳转的时候 this必须要省略否则会报错
    <button @click="$router.back()" >back后退</button>
   <button @click="$router.forward()">forward前进</button>

5 路由导航守卫

导航守卫可以控制路由的访问权限。如下图所示

5.1 全局前置守卫

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

const router = new VueRouter(...)

//调用路由实例对象的beforEach方法,即可声明“全局前置守卫”
// 每次发生路由导航跳转的时候,都会自都动触发fn 这个“回调函数”

router.beforeEach(fn)

5.2守卫方法的 3 个形参

全局前置守卫的回调函数中接收 3 个形参,格式为:

const router = new VueRouter(...)

//全局前置守卫
router.beforeEach((to,from,next)=>
    //to 是将要访问的路由的信息对象
    // from 是将要离开的路由的信息对象
    // next 是一个函数,调用next()表示放行。允许这次路由导航

)

5.3 next 函数的 3 种调用方式

  1. 当前用户拥有后台主页的访问权限,直接放行:next()
  2. 当前用户没有后台主页的访问权限,强制其跳转登录页面:next('/login')
  3. 当前用户没有后台主页的访问权限,不允许跳转到后台主页:next(false)

5.4 控制后台主页的访问权限

// 为router 实例对象 声明全局前置导航守卫
// 只要发生了路由的
router.beforeEach((to, from, next) => 
  console.log(from)
  //to 是将要访问的的路由的信息对象
  // fromm 是将要离开的路由的信息对象
  // next 是一个函数 调用next()表示放行 允许这次对象的运行
  // next()

  // 1、要拿到用户将要访问的hash地址
  // 2、判断hash 地址是否等于 /main
  // 如果等于/main 证明需要登录之后 才能访问成功
  // 如果不等于/main 这不需要登录  直接放行 next()
  //3、如果访问的地址是/main 则需要读取localstorage 里面的值
  // 如果有token 这放行
  // 如果没有token 则强制跳转到登录页面

  if (to.path === '/main') 
    //要访问后台主页
    const token = localStorage.getItem('token')
    if (token) 
      next()
     else 
      // 没有登录强制跳转登录页
      next('/login')
    
   else 
    // 直接放行
    next()
  
)

以上是关于v-router 路由基础的主要内容,如果未能解决你的问题,请参考以下文章

v-router 路由基础

vue路由核心要点(vue-router)

路由基础-静态路由

Vue权限控制——动态注册路由

Vue权限控制——动态注册路由

仅使用 Nuxt 进行服务器端渲染一页