VUE3 路由使用方式和原理

编辑: admin 分类: 电脑知识 发布时间: 2023-06-14 来源:互联网
路由模式有三种模式Hash模式: 使用 URL 的 hash 值来作为路由,用来指导浏览器动作的,对服务器端完全无用,支持所有浏览器。默认使用的是 hash 模式,也就是会出现如 URL:URL中带有#号。History模式: 以来 HTML5 History API 和服务器配置。Abstract模式: 支持所有 javascript 运行模式。如果发现没有浏览器的 API,路由会自动强制进入这个模式。route/index.js
  1. import {
  2. createRouter,//创建路由
  3. createWebHistory,//历史模式
  4. createWebHashHistory,//哈希模式
  5. } from 'vue-router'
  6. import { Toast } from 'vant';
  7. import NProgress from 'nprogress'; // Progress 进度条
  8. import 'nprogress/nprogress.css'; // Progress 进度条 样式
  9. import store from "../store/index";
  10. const xqlist = ()=>import("@/views/xiang/xiang")//用变量形式导入
  11. const routes = [
  12. {
  13. path: "/",//url访问的路径
  14. name: "tabBar",//路由名称
  15. component: ()=>import("@/components/lib/tabBar/index"),//页面导入路径
  16. redirect:{name:'index',query:{id:55}},//域名重定向
  17. alias: /home,//路由别名,
  18. children:[//子页面
  19. // 首页
  20. {
  21. path: "/index",
  22. name: "index",
  23. alias:['/a', '/b', '/c'],//多个别名,alias: ['/:id','']
  24. component: ()=>import("@/views/index/index"),
  25. meta: {//meta里面属性,都可以自定义。
  26. title: '首页',//用于在渲染的时候配置浏览器标题
  27. keepAlive: true,
  28. },
  29. beforeEnter: (to, from) => {//也可以这样单个写路由独享守卫。
  30. document.title = to.meta.title
  31. },
  32. },
  33. // 发现首页
  34. {
  35. path: "/findIndex/:id",//:id(动态路由)
  36. name: "findIndex",
  37. meta: {
  38. title: '发现',
  39. keepAlive: true,
  40. },
  41. component: ()=>import("@/views/find/findIndex/findIndex")
  42. },
  43. // 我的首页
  44. {
  45. path: "/mineIndex",
  46. name: "mineIndex",
  47. meta: {
  48. title: '我的',
  49. keepAlive: true,
  50. requireAuth: true//跳转时候通过这个标识,路由导航检测是否需要验证已登录的
  51. },
  52. component: ()=>import("@/views/mine/mineIndex/mineIndex")
  53. }
  54. ]
  55. },
  56. {
  57. path: "/xiang",
  58. name: "xiang",
  59. meta: {
  60. title: '详情页',
  61. },
  62. component: ()=>import("@/views/xiang/xiang")
  63. //component: xqlist //或者以变量形式导入
  64. },
  65. {//404 路由页面配置
  66. path: "/:pathMatch(.*)*",
  67. name: "404",
  68. component: ()=>import("@/views/lib/404")
  69. },
  70. ];
  71. const router = createRouter({
  72. mode: 'hash',
  73. history: createWebHistory(process.env.BASE_URL),//历史模式
  74. //history: createWebHashHistory(process.env.BASE_URL),//哈希模式
  75. base: process.env.BASE_URL,
  76. // 配置激活时要使用的类名
  77. linkActiveClass:'router-link-active',
  78. routes
  79. });
  80. NProgress.configure({
  81. showSpinner: false
  82. });
  83. //前置守卫,在路由跳转前触发。router.beforeEach()
  84. //全局解析守卫,在导航被确认前,同时在组件内守卫和异步路由组件被解析后router.beforeResolve()
  85. //后置守卫,在路由跳转完成后触发。router.afterEach()
  86. //导航守卫主要用来通过跳转或取消的方式守卫导航
  87. //前置守卫,to即将要进入的目标路由对象, from当前导航正要离开的路由
  88. router.beforeEach((to, from, next) => {
  89. const title = to.meta.title//使用路由元信息meta实现动态页面标题
  90. document.title = title
  91. NProgress.start(); // 开启Progress
  92. if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
  93. if (store.state.token) { // 通过vuex state获取当前的token是否存在
  94. next();
  95. } else {
  96. console.log(to.fullPath);
  97. next()
  98. }
  99. } else {
  100. next();
  101. }
  102. });
  103. // 后置守卫
  104. router.afterEach((to, from) => {
  105. Toast.clear();
  106. NProgress.done(); // 结束Progress
  107. });
  108. export default router;
路由参数传递方式
  • 传递参数主要有两种类型:params 和 queryparams 的类型:
  • 配置路由格式: /user/:id (动态路由)
  • 传递的方式: 在 path 后面对应的值 :to=”’/user/‘+uid”
  • 传递后形成的路径: /user/9, /user/zx
  • 接收参数: $route.params.idquery 的类型:
  • 配置路由格式: /user, 正常配置
  • 传 递 的 方 式 : 对 象 中 使 用 query 的 key 作 为 传 递 方 式 :to={ path:’/‘,query:{id:1,name:’abc’}}
  • 传递后形成的路径:/user?id=9, /user?id=zx
  • 接收参数:$route.query.name
详情等价于route.push({name:’xiang’})" class="reference-link"><router-link to="/xiang">详情</router-link>等价于route.push({name:’xiang’}) 写法 说明 $route.path 字符串,对应当前路由的路径,总是解析为绝对路径,如”/foo/bar”。 $route.params 一个key/value对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象。 $route.query 当前路由的hash值 (不带#) ,如果没有 hash 值,则为空字符串。锚点* $route.fullPath 完成解析后的 URL,包含查询参数和hash的完整路径。 $route.matched 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。 $route.name 当前路径名字 $route.meta 路由元信息
  1. <template>
  2. <!-- query传递单一的方式 -->
  3. <router-link :to="'/user/page/'+item.id">{{item.title}}</router-link>
  4. <!-- query传递必须使用path路径 -->
  5. <router-link :to="{
  6. path:'/xiang',<!-- 路由路径 -->
  7. query:{user:'query小张zhang'}<!-- query传递数据,会显示在URL上面,类似get。 -->
  8. }"
  9. replace<!-- replace属性的作用是页面切换时不会留下历史记录 -->
  10. exact<!-- exact是开启“router-link”的严格模式 -->
  11. custom<!-- 是否不渲染成a标签 -->
  12. >query传递</router-link>
  13. <!-- params传递必须使用name路由名称 -->
  14. <router-link :to="{
  15. name:'xiang',<!-- 路由名称 -->
  16. params:{user:'params小张zhang'}<!-- params传递数据,不会显示在URL上面,类似POST。 -->
  17. }"
  18. >params传递</router-link>
  19. </template>
组件守卫导航 函数沟子名 含义 触发时机说明 onBeforeRouteUpdate 组件内更新守卫 在当前路由改变啊,但是该组件被复用时调用 onBeforeRouteLeave 组件内离开守卫 导航离开该组件路由时调用 原生路由对应VUE路由 原生 VUE window.history.pushState router.push window.history.replaceState router.replace window.history.go router.go
  1. import {
  2. useRoute,//路由信息
  3. useRouter,//操作路由
  4. onBeforeRouteUpdate,//更新(当前重复)路由调用
  5. onBeforeRouteLeave,//离开当前路由调用
  6. RouterLink,
  7. useLink
  8. } from 'vue-router';//引入路由
  9. import { onMounted,watch,watchEffect } from 'vue';
  10. consy router = useRouter()
  11. function gopage(){
  12. this.$router.push({path:'/xiang',query:{a:123}})//选项式写法
  13. this.$router.replace({path:'/xiang',query: {a:123}})//选项式写法,replace属性的作用是页面切换时不会留下历史记录
  14. router.push({name:'xiang',params: {user:'按钮小张zhang'}})//组合式写法
  15. router.push({path:'/xiang',query: {user:'按钮小张zhang'}})//组合式写法
  16. router.go(1)//前进一页,和router.forward() 相同
  17. router.go(-1) // 后退一页,和router.back()相同。
  18. /* router.go(n)和原生window.history.go(n)类似 */
  19. }
  20. // 查询文章详情
  21. async function queryArticleDetail(id: number) {
  22. // 请求接口数据
  23. const res = await axios({
  24. url: `/article/${id}`,
  25. })
  26. }
  27. onMounted(() => {
  28. route.params
  29. })
  30. /* 用法
  31. 1、比如一个内容网站,通常在文章详情页底部会有相关阅读推荐,这个时候就会有一个操作场景是,从文章 A 跳转到文章 B。
  32. 2、比如从 https://www.baidu.com/article/111 请求 https://www.baidu.com/article/222 ,这种情况就属于 “路由改变,但是组件被复用” 的情况了。
  33. 3、这种情况下,原本放在 onMounted 里执行数据请求的函数就不会被调用,可以借助该钩子来实现渲染新的文章内容。
  34. */
  35. onBeforeRouteUpdate(async (to, from) => {
  36. // ID 不变时减少重复请求
  37. if (to.params.id === from.params.id) return
  38. // 注意这里是获取 `to` 的 `params`
  39. const id = Number(to.params.id) || 0
  40. await queryArticleDetail(id)
  41. })
  42. /*用法
  43. 可以在离开当前路由之前,实现一些离开前的判断拦截。
  44. 离开守卫通常用来禁止用户在还未保存修改前突然离开,可以通过 return false 来取消用户离开当前路由。
  45. */
  46. onBeforeRouteLeave((to, from) => {
  47. // 弹出一个确认框
  48. const confirmText = '确认要离开吗?您的更改尚未保存!'
  49. const isConfirmLeave = window.confirm(confirmText)
  50. // 当用户点取消时,不离开路由
  51. if (!isConfirmLeave) {
  52. return false
  53. }
  54. })
  55. /*侦听整个路由
  56. 第一个参数传入整个路由;第二个参数是个 Callback ,可以获取 to 和 from 来判断路由变化情况。
  57. */
  58. watch(route, (to, from) => {
  59. // 处理一些事情
  60. })
  61. /*侦听路由的某个数据
  62. 如果只想侦听路由的某个数据变化,比如侦听一个Query或者一个Param,可以采用这种方式:
  63. */
  64. watch(
  65. () => route.query.id,
  66. () => {
  67. console.log('侦听到 ID 变化')
  68. }
  69. )
  70. /*
  71. 直接侦听包含路由参数的那个函数
  72. 对比 watch 的使用, watchEffect在操作上更加简单,把包含要被侦听数据的函数,当成它的入参传进去即可。
  73. */
  74. watchEffect(queryArticleDetail)
部署问题与服务端配置通常使用路由的 Hash哈希 模式,部署后有问题的情况很少,但是如果使用 History历史 模式,可能会遇到这样那样的问题。常见部署问题这里整理一些常见部署问题的原因分析和解决方案,可作参考。页面刷新就 404页面部署到服务端之后,访问首页正常;通过导航上面的链接进行路由跳转,也正常;但是刷新页面就变成 404 了。问题原因一般这种情况是路由开启了 History 模式,但是服务端没有配置功能支持。解决方案请根据 服务端配置 部分的说明,与的运维同事沟通,让他帮忙修改服务端的配置。部分路由白屏如果在项目配置文件里,把里面的 publicPath (使用 Vue CLI ) 或者 base (使用 Vite ) 配置成相对路径 ./ ,但是路由配置了二级或以上,那么就会出现这个问题。问题原因原因是打包后的 JS 、 CSS 等静态资源都是存放在项目根目录下,一级路由的 ./ 就是根目录,所以访问正常;而二级路由的 ./ 则不是根目录了,是从当前目录载入的 ,这就导致无法正确载入 JS 文件,从而导致了白屏。
假设项目域名是 https://example.com ,那么:一级路由是 https://example.com/home ,二级路由是 https://example.com/foo/bar ,假设打包后的 JS 文件等静态资产存放于 https://example.com/assets/ 文件夹下访问一级路由时, ./ 访问到的 JS 文件是 https://example.com/assets/home.js ,所以一级路由可以正常访问到。访问二级路由时, ./ 访问到的 JS 文件是 https://example.com/foo/assets/bar.js ,但实际上文件是存放在 https://example.com/assets/bar.js ,访问到的 URL 资源不存在,所以白屏了。解决方案如果的项目开启了 History 模式,并且配置有二级或者二级以上的路由时,不要使用 ./ 这样的相对路径。正确的方式应该是修改 publicPath (使用 Vue CLI ) 或者 base (使用 Vite ),如果是部署在域名根目录则写 / ,如果是子目录,则按照子目录的格式,将其以 / 开头,以 / 结尾的形式配置( e.g. /hello-world/ )服务端配置方案如果使用的是 HTML5 的 History 模式,那么服务端也需要配置对应的支持,否则会出现路由跳转正常,但页面一刷新就 404 的情况。服务器配置方案看官网vue router 不同的历史记录模式【感谢龙石为本站提供数据中台建设http://www.longshidata.com/pages/government.html】