经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
万字血书Vue—路由
来源:cnblogs  作者:辜负寒彻骨  时间:2023/3/20 8:44:10  对本文有异议

image
多个路由通过路由器进行管理。

前端路由的概念和原理

(编程中的)路由(router)就是一组key-value对应关系,分为:后端路由和前端路由

后端路由指的是:请求方式、请求地址function处理函数之间的对应关系

在SPA程序中,所有组件的展示和切换都在这唯一的一个页面内完成,此时,不同组件之间的切换需要通过前端路由来实现

通俗易懂的来说,前端路由是:Hash地址(url中#的部分)与组件之间的对应关系

前端路由的工作方式

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

image

实现简易的前端路由(底层实现原理)

App.vue根组件

  1. <template>
  2. <div>
  3. <h1>这是App根组件</h1>
  4. <a href="#/Home">Home</a>&nbsp;
  5. <a href="#/Movie">Movie</a>&nbsp;
  6. <a href="#/About">About</a>&nbsp;
  7. <hr>
  8. <component :is="comName"></component>
  9. </div>
  10. </template>
  11. <script>
  12. import MyHome from './MyHome.vue'
  13. import Mymovie from './MyMovie.vue'
  14. import MyAbout from './MyAbout.vue'
  15. import { walkFunctionParams } from '@vue/compiler-core'
  16. export default {
  17. name:'App',
  18. components:{
  19. MyHome,
  20. MyAbout,
  21. Mymovie,
  22. },
  23. data(){
  24. return{
  25. comName:'MyHome'
  26. }
  27. },
  28. created(){
  29. window.onhashchange=()=>{
  30. switch(location.hash){
  31. case '#/Home':
  32. this.comName='MyHome'
  33. break
  34. case '#/Movie':
  35. this.comName='MyMovie'
  36. break
  37. case '#/About':
  38. this.comName='MyAbout'
  39. break
  40. }
  41. }
  42. }
  43. }
  44. </script>
  45. <style lang="less" scoped>
  46. </style>

vue-router的基本使用

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

二者差异主要是在声明router配置文件上。

vue-router 3.x的基本使用步骤

  • 在项目中安装vue-router
  1. npm install vue-router@3.5.2 -S
  • src源代码目录下,新建router/index.js路由模块
  1. //导入包
  2. import Vue from 'vue'
  3. import VueRouter from 'vue-router'
  4. //插件引入
  5. Vue.use(VueRouter)
  6. //创建路由的实例对象
  7. const router = new VueRouter
  8. //向外共享
  9. export default router
  • 在入口文件main.js中引入
  1. import router from '@/router/index.js'
  2. ......
  3. new Vue({
  4. ...
  5. router:router
  6. ...
  7. }).$mount('#app')

vue-router 4.x的基本使用步骤

  • 在项目中安装vue-router
  1. npm install vue-router@next -S
  • 定义路由组件

MyHome.vue、MyMovie.vue、MyAbout.vue

  • 声明路由链接占位符

可以使用<router-link>标签(会被渲染成a链接)来声明路由链接,并使用<router-view>标签来声明路由占位符

  1. <template>
  2. <div>
  3. <h1>这是App根组件</h1>
  4. <!-- <a href="#/Home">Home</a>&nbsp;
  5. <a href="#/Movie">Movie</a>&nbsp;
  6. <a href="#/About">About</a>&nbsp; -->
  7. <!-- 声明路由链接 -->
  8. <router-link to="/home">首页</router-link>
  9. <router-link to="/movie">电影</router-link>
  10. <router-link to="/about">我的</router-link>
  11. <hr>
  12. <!-- 路由占位符 -->
  13. <router-view></router-view>
  14. <component :is="comName"></component>
  15. </div>
  16. </template>
  • 创建路由模块

从项目中创建router.js路由模块,按照以下四步:

从vue-router中按需导入两个方法

  1. import { createRouter, createWebHashHistory } from 'vue-router'
  2. //createRouter方法用于创建路由的实例对象
  3. //createWebHashHistory用于指定路由的工作方式(hash模式)

导入需要使用路由控制的组件

  1. import MyHome from './MyHome.vue'
  2. import MyMovie from './MyMovie.vue'
  3. import MyAbout from './MyAbout.vue'

创建路由实例对象

  1. const router = createRouter({
  2. history: createWebHashHistory(),
  3. routes: [
  4. {
  5. path: '/home', component: MyHome
  6. },
  7. {
  8. path: '/movie', component: MyMovie
  9. },
  10. {
  11. path: '/about', component: MyAbout
  12. },
  13. ]
  14. })

向外共享路由实例对象

  1. export default router

在main.js中导入并挂载路由模块

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import './index.css'
  4. import router from './components/router'
  5. const app = createApp(App)
  6. //挂载路由写法
  7. app.use(router)
  8. app.mount('#app')
  • 导入并挂载路由模块

vue-router的高级用法

路由重定向

指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特点的组件页面

通过路由规则的redirect属性,指定新的路由地址

  1. const router = createRouter({
  2. history: createWebHashHistory(),
  3. routes: [
  4. {
  5. path: '/home', component: MyHome
  6. },
  7. {
  8. path: '/',redirect:'/home' //访问根路径会重定向到home组件
  9. },
  10. {
  11. path: '/movie', component: MyMovie
  12. },
  13. {
  14. path: '/about', component: MyAbout
  15. },
  16. ]
  17. })
路由传参

query参数

  1. <router-link :to="/about/home/message?id=123&title='abc'">我的</router-link>
  2. <router-link :to="{
  3. path:'/about/home/message',
  4. query:{
  5. id:123,
  6. title:'abc'
  7. }
  8. }">
  9. 我的
  10. </router-link>

params参数

声明时:

  1. path:'/about/home/message/:id/:title'
  1. <router-link :to="/about/home/message/123/abc">我的</router-link>
  2. <router-link :to="{
  3. name:'my',
  4. params:{
  5. id:123,
  6. title:'abc'
  7. }
  8. }">
  9. 我的
  10. </router-link>

this.$route 是路由的"参数对象"

this.$router 是路由的"导航对象"

路由高亮
  • 使用默认的高亮class类名

被激活的路由链接,默认会使用router-link-active的类名,开发者可以使用此类名选择器,为激活的路由链接设置高亮样式

  • 自定义路由高亮的class类

在创建路由的实例对象时,开发者可以基于linkActiveClass属性,自定义类名

  1. const router = createRouter({
  2. history: createWebHashHistory(),
  3. linkActiveClass:'active-router',
  4. routes: [
  5. {
  6. path: '/home', component: MyHome
  7. },
  8. {
  9. path: '/',redirect:'/home' //访问根路径会重定向到home组件
  10. },
  11. {
  12. path: '/movie', component: MyMovie
  13. },
  14. {
  15. path: '/about', component: MyAbout
  16. },
  17. ]
  18. })
嵌套路由

通过路由来实现组件的嵌套展示

步骤:

  • 声明子路由链接和子路由占位符
  1. <template>
  2. <div>MyAbout组件</div>
  3. <hr>
  4. <router-link to="/about/tab1">tab1</router-link>&nbsp;
  5. <router-link to="/about/tab2">tab2</router-link>
  6. <router-view></router-view>
  7. </template>
  • 在父路由规则中,通过children属性嵌套声明子路由规则
  1. const router = createRouter({
  2. history: createWebHashHistory(),
  3. routes: [
  4. {
  5. path: '/home', component: MyHome
  6. },
  7. {
  8. path: '/movie', component: MyMovie
  9. },
  10. {
  11. path: '/about', component: MyAbout,children:[
  12. {
  13. path:'tab1',component:Tab1
  14. },
  15. {
  16. path:'tab2',component:Tab2
  17. },
  18. ]
  19. },
  20. ]
  21. })

子路由规则的path不要以/开头

在嵌套路由中实现路由的重定向

  1. const router = createRouter({
  2. history: createWebHashHistory(),
  3. routes: [
  4. {
  5. path: '/home', component: MyHome
  6. },
  7. {
  8. path: '/movie', component: MyMovie
  9. },
  10. {
  11. path: '/about',
  12. component: MyAbout,
  13. redirect:'/about/tab1',
  14. children:[
  15. {
  16. path:'tab1',component:Tab1
  17. },
  18. {
  19. path:'tab2',component:Tab2
  20. },
  21. ]
  22. },
  23. ]
  24. })
动态路由匹配

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

  1. {
  2. path: '/movie/:id', component: MyMovie
  3. },

获取动态路由参数值的方法:

  • $route.params参数对象
  1. <template>
  2. <div>Mymovie组件---{{$route.params.id}}</div>
  3. </template>
  • 使用props接受路由参数
  1. {
  2. path: '/movie/:id', component: MyMovie,
  3. props: true,
  4. },

为了简化路由参数的获取形式,vue-router允许在路由规则开启props传参

编程式导航

通过调用API实现导航的方式,叫做编程式导航,与之对应的,通过点击链接实现导航的方式,叫做声明式导航

  • 普通网页中点击a链接,vue项目中点击<router-link>都属于声明式导航
  • 平台网页中调用location.herf跳转到新页面的方式,属于编程式导航

vue-router中编程式导航API

  • this.$router.push('hash地址') 跳转到指定Hash地址,并增加一条历史记录,从而展示对应的组件。
  • this.$router.replace('hash地址') 跳转到指定Hash地址,并替换当前的历史记录,从而展示对应的组件。
  • this.$router.go('数值n') 实现导航历史的前进、后退(-1),超过最大层数,则原地不动。

$router.back() 后退到上一层页面

$router.forward() 前进到下一层页面

命名路由

通过name属性为路由规则定义名称,叫做命名路由,name值不能重复,具有唯一性

Hash地址特别长时体现出命名路由的优势

  • 使用命名路由实现声明式导航
  1. <template>
  2. <h3>
  3. MyHome组件
  4. </h3>
  5. <router-link :to="{name:'mov',params:{id : 3}}">goToMovie</router-link>
  6. </template>
  7. <script>
  8. export default {
  9. name:'MyHome',
  10. }
  11. </script>
  • 使用命名路由实现编程式导航
  1. <template>
  2. <h3>
  3. MyHome组件
  4. </h3>
  5. <button @click="goToMovie(3)">
  6. goToMovie
  7. </button>
  8. </template>
  9. <script>
  10. export default {
  11. method: {
  12. goToMovie(id) {
  13. this.$router.push({name:'mov',params:{id : 3}})
  14. }
  15. }
  16. }
  17. </script>
导航守卫

导航守卫可以控制路由的访问权限

image

如何声明全局的导航守卫

全局的导航守卫会拦截每个路由规则,从而对每个路由都进行访问权限的控制

  1. const router = createRouter({
  2. ...
  3. })
  4. //调用路由实例对象的beforeEach函数,fn必须是一个函数吗,每次拦截后,都会调用fn进行处理
  5. //声明全局的导航守卫,fn称为守卫方法
  6. router.beforeEach(fn)
  7. router.beforeEach(()=>{
  8. console.log('Ok')
  9. })

守卫方法的三个形参(可选)

  1. router.beforeEach((to,from,mext)=>{
  2. console.log('Ok')
  3. //to 目标路由对象(信息)
  4. //from当前导航正要离开的路由对象
  5. //next 是一个函数,表示放行
  6. })

注:

在守卫方法中不声明next形参,则默认允许用户访问每一个路由

在守卫方法中声明了next形参,则必须调用next()函数,否则不允许用户访问如何一个路由!

next函数的3种调用方式

  1. //声明全局的导航守卫
  2. router.beforeEach((to, from, next) => {
  3. if (to.path === '/main') {
  4. //证明用户要访问后台主页
  5. next(false)//强制用户停留在之前所处的组件
  6. next('login')//强制用户调转到指定页面
  7. } else {
  8. //证明用户要访问的不是后台主页
  9. next()
  10. }
  11. })

结合token控制后台主页的访问权限

  1. router.beforeEach((to, from, next) => {
  2. const tokenStr = localStorage.getItem('token') //读取token
  3. if (to.path === '/main' && !tokenStr) { //token不存在,需要登录
  4. //证明用户要访问后台主页
  5. // next(false)//强制用户停留在之前所处的组件
  6. next('login')//强制用户调转到指定页面
  7. } else {
  8. //证明用户要访问的不是后台主页
  9. next()
  10. }
  11. })

Hash&History

路由器的两种工作模式:hash&history

对于url来说:#及后面的内容就是hash值,hash值不会带给服务器。

hash模式:

  1. 地址中永远带着#号,不美观;
  2. 若地址校验严格,会被标记为不合法;
  3. 兼容性较好;

history模式:

  1. 地址干净,美观;
  2. 兼容性比hash模式较差;
  3. 应用部署上线需要后端支持,解决刷新页面服务端404问题;(node可以使用connect-history-api-fallback

原文链接:https://www.cnblogs.com/gfhcg/p/17232523.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号