Vue Router4

后端路由

  1. 客户端请求不同的URL
  2. 服务器匹配URL并给一个Controller处理
  3. Controller处理完返回渲染好的HTML页面或数据给前端

优点:
不需要单独加载js和css,直角交给浏览器展示,有利于SEO优化

缺点:
页面有后端人员编写或由前端人员使用PHP/Java编写

前端路由

  1. 前后端分离:后端提供API,前端渲染数据到页面上
  2. SPA(单页面富应用):前后端分离+前端路由
  3. 前端路由核心:URL和组件相互映射。改变URL,页面不整体刷新

改变URL 页面不刷新的两种模式

  1. URL的hash(锚点#),H5的API location
<template>
  <div>
    <a href="#/home">首页/</a>
    <a href="#/about">关于/</a>
    <div class="router-view" ref="divRef"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'

// 获取DOM
let divRef = ref()

// DOM挂载完成
onMounted(() => {

  // 监听hash值的改变(相当与监听URL的改变)
  window.addEventListener('hashchange', () => {
    switch (location.hash) {
      case "#/home":
        divRef.value.innerHTML = "home"
        break;
      case "#/about":
        divRef.value.innerHTML = "about"
        break;
      default:
        divRef.value.innerHTML = "default"
        break;
    }
  })
})

</script>
  1. H5新增API的history
    history实例方法,改变URL而不刷新页面:
    back()
    forward()
    go()
    pushState()
    replaceState()

基本使用

路由映射文件

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      component: () => import('@/views/AboutView.vue')
    }
  ]
})

export default router

App.vue

<template>
  <div>
    <!-- 字符串形式 -->
    <router-link to="/">首页</router-link>
    <router-link to="/about">关于</router-link>
    <!-- 对象形式 -->
    <router-link :to="{ path: '/about' }">关于</router-link>

    <!-- 路由出口 -->
    <router-view></router-view>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'

</script>

<style scoped>
/* 高亮 */
.router-link-active {
  color: red;
  font-size: 20px;
}
</style>

动态路由(路径参数)

params参数

动态路由:根据匹配模式,不同路径的路由映射到同一个组件

匹配模式匹配路径$route.params
/users/:username/users/eduardo{ username: 'eduardo' }
/users/:username/posts/:postId/users/eduardo/posts/123{ username: 'eduardo', postId: '123' }

匹配模式

{
	path: '/user/:id',
	name: 'user',
	component: () => import('@/views/UserView.vue')
}

App.vue传递参数

<template>
  <div>
    <router-link to="/">首页</router-link>
    <router-link to="/about">关于</router-link>
    <!-- 给路由传参 -->
    <router-link :to="{ path: `/user/${id}` }">用户{{ id }}</router-link>
    <router-link to="/user/2">用户2</router-link>

    <!-- 路由出口 -->
    <router-view></router-view>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
let id = ref(100)
</script>

<style scoped>
/* 高亮 */
.router-link-active {
  color: red;
  font-size: 20px;
}
</style>

UserView.vue接收参数

<template>
  <div>
    <!-- 
      UserView接收到params参数,根据不同id进行不同操作
     -->
    <h1>user-{{ $route.params.id }}</h1>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRoute } from 'vue-router';

const route = useRoute()
console.log(route.params);

</script>

在这里插入图片描述
在这里插入图片描述

query参数

App.vue传递query参数

const router = useRouter()
function handleClick() {
  router.push({
    path: '/user/2',
    query: {
      name: 'cjc',
      age: 999
    }
  })
}
// http://127.0.0.1:5173/user/2?name=cjc&age=999

UserView.vue接收参数

<!-- query参数 -->
<h1>query-{{ $route.query }}</h1>
const route = useRoute()
console.log(route.query);

路由改变 组件复用

用户从 /user/1 导航到 /user/2 时,相同的组件实例UserView被重复使用。
因为组件没有销毁创建,故组件的生命周期钩子不会被调用

监听同一路由组件的路径参数的变化:

方式1 在UserView中使用watch

// 监听参数变化
watch(() => route.params, (toParams, previousParams) => {
  // 对路由变化做出响应
  console.log('toParams:', toParams);
  console.log('previousParams:', previousParams);
})

方式2 在UserView中使用onBeforeRouteUpdate

onBeforeRouteUpdate((to, from) => {
  console.log('to:', to.params);
  console.log('from:', from.params);
})

404

{
 //path: '/:pathMatch(.*)' 匹配内容以/形式
 //path: '/:pathMatch(.*)*' 匹配内容以数组形式
 path: '/:pathMatch(.*)*',
 name: 'NotFound',
 component: () => import('@/views/NotFound.vue')
}

将匹配所有内容并将其放在 $route.params.pathMatch

编程式路由导航

$router相关API

  • go
  • forward
  • back
  • push
  • replace

动态添加路由

router/index.js

...
// 动态添加路由
// 添加一级路由
router.addRoute({
  path: '/test',
  name: 'test',
  component: () => import("@/views/TestView.vue")
})

// 添加二级路由
// testChild不会添加到test的children中
router.addRoute("test", {
  path: 'testChild',
  name: 'testChild',
  component: () => import("@/views/TestChildView.vue")
})

// 检查路由是否存在
console.log(router.hasRoute('test'));

// 路由器router中所有路由
console.log(router.getRoutes());

// 删除路由,所有的别名和子路由也会被同时删除
router.removeRoute('test')
console.log(router.getRoutes());

路由导航守卫

全局前置守卫beforeEach

参数

  • to “到哪去”的路由对象
  • from “从哪来”的路由对象

返回值

  • return false 取消当前导航
  • return;或return undefined;都是默认导航。等同于return to.path;
  • return 路由地址(string|对象(包含path,query,params))

登录导航守卫

在导航守卫中添加路由

router.beforeEach(to => {
  if (!hasNecessaryRoute(to)) {
    router.addRoute(generateRoute(to))
    // 触发重定向
    return to.fullPath
  }
})

hasNecessaryRoute() 在添加新的路由后返回 false,以避免无限重定向。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值