【vue3 路由使用与讲解】vue-router : 超详细全面介绍

# 核心内容介绍

路由跳转有两种方式:

  • 声明式导航:<router-link :to="...">

  • 编程式导航:router.push(...) 或 router.replace(...) ;两者的规则完全一致。

    • push(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>

      replace(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>;

  • 由于属性 torouter.push 接受的对象种类相同,所以两者的规则完全相同。

路由传参有两种方法:

  • params:使用动态路由的方式进行传参;
    • 只为了传参则不建议用params,params 主要是用来进行动态路由匹配的。
    • 声明为动态路由,params则是必传的!除非设置为可选!
    • 声明路由时设置该路由props参数为true,则会改变功能形态。(傻逼功能,别用)
  • query:拼接在url后面,以?的方式隔开;/urlpath?d1="666"&d2=逆天&arr=["1"]&b=true
    • 传参时仅建议 string | number | (string|number)[] 类型的数据 ,否则编辑器会 ts 报错提示。
  • 所有传参的数据类型如果非字符串会自动字符串化 >> String(xx)
  • params 和 query 的 TS 类型为:string | string[]。也就意味着它并不希望你放乱七八糟的东西在url上,即便你JSON.stringify() 转换过了。

动态路由:

  • 动态路由的跳转必须是 name + params,用 path 跳转命名路由将无效;且 params 必传!
  • 动态路由以 `/path1/:id` 的方式进行声明,跳转路径结果为 /path/1
  • 动态路由设置的参数例如 :id ,可以将该参数设置为可选参数 `/path1/:id?` ,这样params就是可传可不传了。

命名路由:

  • 就是声明了路由的 name。name值是唯一的,不管是顶级路由还是嵌套路由。
  • 如果是跳转嵌套路由里的子路由,path 跳转需要/xx/xx/child,可直接用该子路由的name。
  • 没有硬编码的 URL
  • params 的自动编码/解码。
  • 防止你在 url 中出现打字错误。
  • 绕过路径排序(如显示一个)

# 说明:

$route / route: 有当前路由的所有信息!

$router / router: 用来进行路由操作的!


# 声明路由

如何声明路由

  • 必备的 path component。其他一堆属性自己了解相关功能就知道什么时候是必要的,什么时候是非必要的了。有用点的就是name redirect children meta了。

顶级路由

  • 最外层的路由

嵌套路由

  • 声明路由的 children
  • 嵌套路由不限层级
  • 想要默认加载一个子路由的话将path设置为空字符串:` path:"" `。
  • 跳转嵌套路由最好使用 name 方式跳转,降低心智负担!

声明为动态路由,上面讲过了,忘了?别怕,那下面代码也有示例。

路由重定向

  • redirect: { name: 'routeName' }, 设置为路由的name最保险,别想着其他花里胡哨的。

  • 在写 redirect 的时候,如果不是嵌套路由,可以省略 component 配置。
    你重定向到自己的子路由,那肯定要有 component 啊,不然你 router-view 在哪(笑)

命名视图

  • component 变 components,具体看代码

  • 本示例包含 path , name , meta , component , components , children , redirect , props , 路由懒加载 , alias 。

javascript 复制代码
import { createRouter, createWebHistory } from 'vue-router'

export const router = createRouter({
  history: createWebHistory(), // 设置路由模式
  routes: [
    {
      // 普通的设置一个普通的路由(顶级路由)
      path: '/',
      name: 'HelloWorld',
      meta: { requiresXXX: true }, // 设置路由元信息,应用场景的话:主要就路由守卫里用的会多一点。该数据只能在这里声明,其他途径无法修改。
      component: () => import('../components/HelloWorld.vue') // 设置路由懒加载
    },
    {
      path: '/routerVue/:id', // 设置为动态路由,id则必传
      // path: '/routerVue/:id?', // 设置该动态路由的 id 为可选参数,变为非必传
      name: 'routerVue',
      component: () => import('@/components/xxx.vue')
    },
    {
      path: '/demo',
      alias: '/hellow', // 你访问 /hellow,页面url路径会保持为/hellow,但是路由匹配则为/demo,显示 yyyyyy.vue 组件内容
      component: () => import('@/components/yyyyyy.vue')
    },
    {
      path: '/edit:id?',
      name: 'edit',
      // redirect: { name: 'profile' }, // 路由重定向,访问 /edit 直接重定向为 /edit/profile
      component: () => import('../components/edit.vue'),
      props: true, // 设置为true 则在路由组件中,动态路由的参数 会直接放在vue的 props 里。 // 完全不推荐的写法,增加心智负担。
      children: [ // 设置为嵌套路由
        {
          // 当 /edit 匹配成功
          // demo2.vue 将被渲染到 edit 的 <router-view> 内部
          path: '', // 路径为'',需要增加name,不然会抛出警告。
          component: () => import('../components/demo2.vue'),
          // 命名视图功能: component 变为 components ,然后设置对应视图组件的名称
          // components:{ // 注意加 s 。。。
          //   default: () => import('../components/router-test1.vue'),
          //   template1: () => import('../components/router-test2.vue'),
          // },
          // props: {default: true , template1: false} // 可以为每个命名视图定义 props 配置。还可设置为函数模式(超不推荐,提高代码维护理解难度,对功能方面没任何提升)
        },
        {
          // 当 /edit/profile 匹配成功
          // demo.vue 将被渲染到 edit 的 <router-view> 内部
          path: 'profile',
          name: 'profile',
          component: () => import('../components/profile.vue'),
        }]
    },
    {
      // 匹配所有路径,当上述路径都不满足时,跳转到404页面
      // 如果项目是有动态添加路由的,注意一定要把该404路由提取出来,等动态添加完路由,再把404添加到动态路由的最后一个。
      path: '*',
      name: '404',
      component: () => import('../components/404.vue'),
    },
  ],
})

# 路由跳转的多种写法:

声明式导航写法:

html 复制代码
<router-link :to="{ name: 'vue33', params: { id: 110 }, query: { d1: 'wuwu~~~' } }">vue3.3/3.4新特性</router-link>

编程式导航写法:(options api里的方式)

javascript 复制代码
this.$router.push({
  name: 'vue33',
  params: {
    id: 110
  },
  query: {
    data: 666
  }
})

编程式导航写法:(composition api里的方式)

javascript 复制代码
import { useRouter  } from 'vue-router'
let router = useRouter()
function tiaozhuan() {
  router.push({
    name: 'vue33',
    params: {
      id: 110
    },
    query: {
      data: 666
    }
  })
}

replace 是当前页面替换新页面,路由历史记录里不会保存当前页。

javascript 复制代码
import { useRouter  } from 'vue-router'
let router = useRouter()
function tiaozhuan() {
  router.replace({
    name: 'vue33',
    params: {
      id: 110
    },
    query: {
      data: 666
    }
  })
}

如果是嵌套路由则是父路由path + 子路由path,或者子路由的name,并且跳转时,如果父路由是命名路由,则params也会是必传!


# 获取路由参数

跳转目标路由,声明了params或query之后,(选项式api写法) 通过this.route.params 或 this.route.query 即可拿到对应的路由参数;

组合式API写法如下:

javascript 复制代码
import { useRoute } from 'vue-router'

let route = useRoute()

console.log(route.params);
console.log(route.query);
console.log(route.meta);

# 重新提醒:

route: 有当前路由的所有信息

router: 用来进行路由操作的!


# 路由的导航守卫

  • 全局守卫;

    • beforeEach :全局前置守卫 (1)
    • beforeResolve :全局解析守卫 (3)
    • afterEach:全局后置钩子,该钩子在已经进入该路由后触发,所以无需return true 或 next()。 (4)
  • 路由独享的守卫:

    • beforeEnter :在所有组件内守卫和异步路由组件被解析之后调用。(2)
  • 组件守卫:有3个,其中2个没屁用。

    • beforeRouteEnter :能处理的 beforeEnter 都可以。

    • beforeRouteUpdate :更没必要,直接 watch route.params 即可。

    • beforeRouteLeave :有点用,如果用户跳转路由时,当前页面编辑内容未保存,则可以 return false 取消路由跳转。(setup 内则手动引入 onBeforeRouteLeave)

  • 触发顺序(1)(2)(3)(4)。

    • 组件守卫其中2个懒得算,如果算上 beforeRouteLeave 那 beforeRouteLeave 排在beforeEach 前面。

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

  • to: 即将要进入的目标 。
  • from: 当前导航正要离开的路由 。
  • next: 可选的第三个参数 。(现在根据return 结果来决定了,且更安全(确保调用一次),所以基本不需要next了)
javascript 复制代码
import { createRouter } from 'vue-router'
const router = createRouter({ ... })

router.beforeEach((to, from) => {
  // ...

  return false  
  // 返回 false 以取消导航
  // 如果什么都没有,undefined 或返回 true,则导航是有效的,并调用下一个导航守卫

  // return { name: 'Login' } // 将用户重定向到登录页面
})

# 动态添加路由

javascript 复制代码
//! 动态添加路由、删除路由、添加嵌套路由
router.addRoute({ path: '/about', component: xxx })

// 当路由被删除时,所有的别名和子路由也会被同时删除
// 会返回一个回调,调用该函数即可删除路由 (这种方式可以保证删的更准点吧。。。)
const removeRoute = router.addRoute({ path: '/about', component: xxx })
removeRoute()
// router.removeRoute('about') 通过路由名称进行删除,路由表有同名的话需要注意点(建议路由表name都是唯一的!)

// 添加嵌套路由
// router.addRoute({ name: 'admin', path: '/admin', component: Admin })
// router.addRoute('admin', { path: 'settings', component: AdminSettings })
//> 上述代码等同如如下:
// router.addRoute({
//   name: 'admin',
//   path: '/admin',
//   component: Admin,
//   children: [{ path: 'settings', component: AdminSettings }],
// })

# 查看现有路由

Vue Router 提供了两个功能来查看现有的路由:


# 路由缓存、过渡

<router-view>、<keep-alive> 和 <transition>​

transition 和 keep-alive 现在必须通过 v-slot API 在 RouterView 内部使用:

html 复制代码
<router-view v-slot="{ Component }">
  <transition>
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
  </transition>
</router-view>

# 路由模式

  • Hash 模式:createWebHashHistory
  • HTML5 模式:createWebHistory
javascript 复制代码
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    //...
  ],
})

html5模式需要在服务器上设置初次访问如果404时,进行路由回退:

nginx 如下:

bash 复制代码
location / {
  try_files $uri $uri/ /index.html;
}

其他的详见官网;

相关推荐
一枚前端小能手3 分钟前
Vue3 开发中的5个实用小技巧
前端
Sawtone3 分钟前
shadcn/ui:我到底是不是组件库啊😭图文 + 多个场景案例详解 shadcn + tailwind 颠覆性组件开发,小伙伴直呼高端
前端·面试
柏成3 分钟前
qiankun 微前端框架🐳
前端·javascript·vue.js
Sherry0077 分钟前
终极指南:彻底搞懂 React 的 useMemo 和 useCallback!(译)
前端·react.js
穷小白11 分钟前
Vue3与Ue通信
前端·javascript
柏成15 分钟前
qiankun 源码解析🐳
前端·javascript·面试
前端一课18 分钟前
归元修道后篇
前端
奇舞精选21 分钟前
RAG优化策略
前端
临江仙45522 分钟前
Electron 自动更新全攻略:从 0 到 1 实现企业级 AppUpdater 组件(附完整代码)
前端·javascript
泡岩浆的child25 分钟前
发现一些老代码都是用var声明变量的,现在却几乎不用var关键字了?
前端