Vue-Route4 ts

小满学习视频
Vue-Route 官网

项目的目录结构:

1. Vue-Router的使用

安装Vue-route

javascript 复制代码
pnpm add vue-router@4

创建router文件

  • /route/index.vue
javascript 复制代码
import { createRouter } from "vue-router";
import {
  createMemoryHistory,
  createWebHashHistory,
  createWebHistory,
} from "vue-router";

import type { RouteRecordRaw } from "vue-router";
// 2. 定义路由
const routes: RouteRecordRaw[] = [
  {
    path: "/",  // 浏览器中的路径
    name: "login", // 路由名称(非必需)
    component: () => import("@/views/login.vue"), // 路由组件
  },
  {
    path: "/home",
    name: "home",
    component: () => import("@/views/home.vue"),
  },
  {
    path: "/about",
    component: () => import("@/views/about.vue"),
  },
];
// 1. 创建路由器实例
const router = createRouter({
  // 缺点:浏览器没有前进后退按钮
  history: createMemoryHistory(),
  // 缺点:地址中有#号不美观;优点:兼容性是最好的,不需要服务器做任何配置
  // history: createWebHashHistory(),
  // 缺点:需要服务器做适配;优点:支持浏览器的前进/后退;
  // history: createWebHistory(),
  routes,
});

export default router;
  • 关于历史记录模式
    • 历史记录模式共有三种,各有优缺点
    • 官网推荐使用createWebHistory,后端服务器的配置也不麻烦
    • 不注重美观的后台管理网站中推荐使用createWebHashHistory
  • routerroute两个的关系
    • router:路由器,是路由的管理者,管理着所有的路由
    • route:路由,一条一条的线路,浏览器url对应着vue

在main.ts中全局引用该插件

javascript 复制代码
// 引入插件vue-router
import router from './router'

createApp(App).use(router).mount('#app')

如何使用

在template中通过router-link导航

  • App.vue代码
html 复制代码
<template>
  <div>
    <!-- 通过路由的name 属性,跳转到对应的路由地址  -->
    <router-link :to="{ name: 'home' }">主页</router-link>
    <!-- 通过路由的path 属性,跳转到对应的路由地址 -->
    <router-link to="/about">关于</router-link>
    <router-link to="/">登录</router-link>
  </div>
  <hr />
  <router-view></router-view>
</template>

<script setup lang="ts"></script>
  • router-link:可理解为特殊的a标签,不同的是router-link不会在跳转时引起页面的抖动
  • router-view:可理解为占位符,会在它所在的位置渲染当前 URL 路径对应的路由组件

在script中通过router实例导航(编程式导航)

  • 在实际应用中,通常在渲染某个页面时需要执行一些操作,要使用编程式导航
html 复制代码
父组件App.vue
<template>
  <div>
    编程式导航:
    <button @click="toLogin">登录</button>
    <button @click="toHome('/home')">主页</button>
    <button @click="toAbout('/about')">关于</button>
    <button @click="toLogin1('login')">登录</button>
  </div>
  <hr />
  <router-view></router-view>
</template>

<script setup lang="ts">
// 获取路由器实例
const router = useRouter();
console.log(router);

// 返回当前路由地址
const route = useRoute();
console.log(route);

// 字符串形式跳转
const toLogin = () => {
  router.push("/");
};
// 字符串传参
const toHome = (url: string) => {
  router.push(url);
};
// 对象的形式,传入path
const toAbout = (url: string) => {
  router.push({
    path: url,
  });
};
// 对象形式,传入name
const toLogin1 = (name: string) => {
  router.push({
    name,
  });
};
</script>
  • Router实例
    • 获取Router实例:const router = useRouter();
    • 路由器实例中有什么:
  • Route实例
    • 获取Route实例:const route = useRoute();
    • Route实例中有什么:

replace 不保存历史记录

  • <router-link>加入属性replace
html 复制代码
<router-link replace to="/">登录</router-link>
  • 编程式导航,跳转使用router.repalce
javascript 复制代码
// 字符串形式跳转
const toLogin = () => {
  router.replace("/");
};
  • 前进、后退
typescript 复制代码
    <button @click="next">前进</button>
    <button @click="prev">后退</button>


// 页面前进
const next = () => {
	// go中的数字代表前进几个页面
    router.go(1)
}
// 页面后退
const prev = () => {
    // router.go(-1)
    router.back()
}
  • router实例中可以看到back方法其实调用的就是go(-1)方法

2. 路由传递数据

2.1 query传参

  • 和向服务器发送get请求一样,通过浏览器传递参数

  • 发送方代码:

javascript 复制代码
import { useRouter} from "vue-router";
const data = ref({
    name:"Tom",
    age:18
})
const router = useRouter();
// 通过query传参
const sendData = () => {
    router.push({
        // path:"/about",
        name:"about",
        query:data.value
    })
}
  • 接收方代码:
javascript 复制代码
<template>
  <div>
    姓名:{{ route.query.name }} <br>
    年龄:{{ route.query.age }}
  </div>
</template>

<script setup lang="ts">
import { useRoute } from "vue-router";
const route = useRoute();
  • 浏览器中显示
javascript 复制代码
http://localhost:5173/about?name=Tom&age=18

3. 嵌套路由children

  • 重点是children[]
typescript 复制代码
const routes1: RouteRecordRaw[] = [
  {
    path: "/user", // 浏览器中的路径
    name: "f-route", // 路由名称(非必需)
    component: () => import("@/router-child/fRoute.vue"), // 路由组件
    children: [
      {
        path: "", // 默认加载子路由
        name: "sonRoute1",
        component: () => import("@/router-child/sonRoute1.vue"),
      },
      {
        path: "sonRoute2",
        name: "sonRoute2",
        component: () => import("@/router-child/sonRoute2.vue"),
      },
    ],
  },
];

使用子路由

path/开头的是绝对路径,它是完整路径不受父路径影响,没有/是相对路径,需要向上找父级路径,直到找到带/的路径,并且把路径都拼接起来

  • <router-link>使用的是绝对路径:父路由的path+/+子路由的path
html 复制代码
  <router-link to="/user">第一个子路由</router-link>
  <router-link :to="{name:'sonRoute2'}">第二个子路由</router-link>
  <router-view></router-view>

4. 命名路由components

  • 在routes中定义组件的名字
    1. 同一视图中展示多个组件,使用components的对象形式
    2. 给组件起个名字(名字随意,没有限制)
javascript 复制代码
const routes2: RouteRecordRaw[] = [
  {
    path: "/", // 根路径
    component: () => import("@/name-views/root.vue"), // 路由组件
    children: [
      {
        path: "showLeft", 
        name: "showLeft",
        components:{
           default:() => import("@/name-views/a.vue"), // default对应的是<router-view></router-view>
           bbb:() => import("@/name-views/b.vue"),	// bbb对应的是 <router-view name="bbb">
        }
      },
      {
        path: "showRight",
        name: "showRight",
        components: {
          default:() => import("@/name-views/a.vue"),
          ccc:() => import("@/name-views/c.vue"), // ccc对应的是 <router-view name="ccc">
        }
      },
    ],
  },
];
  • 在vue中使用命名组件
    1. components中的default对应到vue中的代码是<router-view></router-view>
    2. components中包含几个组件,浏览器中显示几个组件的视图
    3. 组件在浏览器的位置是由<router-view>所在的位置决定的
html 复制代码
  <router-link to="/showLeft">显示左侧导航</router-link><br />
  <router-link :to="{name:'showRight'}">显示右侧导航</router-link>
  <div>
    <router-view name="bbb"></router-view>
    <router-view></router-view>
    <router-view name="ccc"></router-view>
  </div>
  • 浏览器显示结果

5. 重定向redirect

访问某一个路由时,自动跳转到重定向的路由

  • 字符串形式
javascript 复制代码
 const routes: RouteRecordRaw[] =[
	{
		path:"/",
		redirect::"/home", // 使用绝对路径 
	}
]
  • 对象形式
javascript 复制代码
 const routes: RouteRecordRaw[] =[
	{
		path:"/",
		redirect:{
     		 // path:"/home" 
      		name:"home"
    	},
	}
]
  • 方法
javascript 复制代码
const routes = [
  {
    path: '/',
    redirect: to => {
      console.log(to) // to:当前路径的相关信息
      return { 
      	path: '/home', // 重定向的绝对路径
      	query: { name:"小满" } // 通过路由传参,看上面的query传参
      	}
    },
  },
]

6. 别名alias

就是给路径起个别的名字,必须是绝对路径

  • 字符串
javascript 复制代码
 const routes: RouteRecordRaw[] =[
	{
		path:"/",
		alias:"/xiaoman",
	}
]
  • 数组方式
javascript 复制代码
 const routes: RouteRecordRaw[] =[
	{
		path:"/",
		alias:["/xiaoman","/daman"],
	}
]
  • 使用
javascript 复制代码
http://localhost:5173/daman
http://localhost:5173/xiaoman

上面的两个地址都是指向
http://localhost:5173/

7. 路由守卫

  • 在路由发生跳转前,和跳转发生后执行一些代码
  • 特别注意:在守卫中跳转后,也是发生了路径的变化,所以还会重新走一次路由守卫,小心死循环

前置守卫

  • 当浏览器中地址发生改变时触发
javascript 复制代码
import router from "./index" // 记得导入已经创建的路由器router

router.beforeEach((to, from) => {
    console.log("to:" ,to, "from:",from)
})
  • 在守卫中的路由跳转
javascript 复制代码
router.beforeEach((to, from) => {
    // 各种条件判断
    if(to.path !== '/' && !localStorage.getItem('token')){
    	
    	return false 	// 取消当前的导航,不会向任何路由跳转
        
        return "/" 		// return的值会赋值到 to.path
       
        return { path: '/' }	// return一个对象
        
        return {name:'login'}
    }
})
  • to将要进入的目标路由

  • from 将要离开的路由

  • 第三个参数next(官网不建议使用)

next()的作用:next()就是通过的意思,但是通过后会继续走剩下的代码,并且next()在代码中会调用多次,不容易察觉错误

javascript 复制代码
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})

后置守卫

  • 路由加载后执行,执行的时间在vue组件加载之前
javascript 复制代码
router.afterEach((to, from) => {
	// todo
})

实现页面加载进度条nprogress

小满视频里面是手写的,我看的困,使用现成的

首先这个进度条是假的,并不能真正的表示加载页面的进度

  • 安装
java 复制代码
pnpm add nprogress
  • 在路由中使用
javascript 复制代码
import NProgress from "nprogress"
import 'nprogress/nprogress.css' //这个样式必须引入

NProgress.configure({ showSpinner: false }); // 取消右侧的转圈圈
// 页面跳转时开始
router.beforeEach((to, from) => {
    NProgress.start() // 
})
// 路由成功跳转完成后
router.afterEach((to, from) => {
    NProgress.done()
})
  • 效果

8. 路由元信息

路由中添加meta属性

  • 在每条单独的路由上可以添加meta属性,meta属性是一个对象,对象中可以添加很多信息
json 复制代码
  {
     path:"/",
     component: () => import("@/views/index.vue"),
     meta:{
       title:'标题栏显示',
       show: true,
     }
   }

.d.ts中增加meta的类型

javascript 复制代码
import "vue-router"
declare module 'vue-router'{
    interface RouteMeta{
        title:string
        icon?:string
    }
}

在守卫中获取meta

javascript 复制代码
router.beforeEach((to, from) => {
    // to.meta
    document.title = to.meta.title
})

vue中获取meta

javascript 复制代码
import {useRoute} from 'vue-router'
const route = useRoute()
console.log(route.meta.title)

获取父级路由的meta

假设当前路由有父级路由,则通过数组matched[]访问

javascript 复制代码
import {useRoute} from 'vue-router'
const route = useRoute()
console.log(route.meta.title) // 当前路由的meta
console.log(route.matched[0].meta.title) // 父级路由的meta

9. 路由应用示例

1.过渡动效

  • <router-view>加动画效果

使用animatecss的动画效果,参考:animatecss动画效果

  • 安装animatecss
javascript 复制代码
pnpm add animate.css
  • 在元数据中加入要采用的动画效果
javascript 复制代码
  {
    path: "/",
    name: "login",
    component: () => import("@/views/login.vue"),
    meta: {
      title: "登录",
      transition:"animate__fadeInDown" // 动画效果来自animatecss
    },

记得修改.d.ts中RouteMeta的类型

  • 在要使用动效的vue中引入
javascript 复制代码
import "animate.css";
html 复制代码
<template>
  <div>
    <router-view #default="{route,Component}"> 
    <!-- 在路由的meta中配置的动画效果,放在这里使用 -->
        <Transition  :enter-active-class="`animate__animated ${route.meta.transition}`">
            <component :is="Component"></component>
        </Transition>
    </router-view>
  </div>
</template>
  • 插槽中的routeComponent是固定的,这段代码中唯一能修改的就是Transition标签 的属性
  • route:当前路由,通过route.meta访问元数据中的值
  • Component:vNode,路由即将加载的vue组件

2. 滚动行为

  • 记录某个组件的滚动距离,跳转到别的路由再返回时,自动滚动到刚才的位置
javascript 复制代码
const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {	// savedPosition记录滚动的距离
    // return 期望滚动到哪个的位置
    // 有滚动就滚动到记录的位置,没有滚动就回到初始位置
    return savedPosition ? savedPosition : { left: 0, top: 0 };
  },
});
  • 为什么不能直接return savedPosition,如果vue中没有设置滚动条,savedPosition返回值是null,会报错

  • style="overflow: auto;"想要记录滚动位置,必须在当前的vue中添加该样式

    假设有父级的vue,两个子级的vue,想要在两个子级的vue中记录滚动行为,那么两个子级的vue必须都加上 style="overflow: auto;";如果只在父级中加该样式,滚动是可以实现,但是savedPosition的值为null

  • 延时滚动

javascript 复制代码
  scrollBehavior(to, from, savedPosition) {
    // return 期望滚动到哪个的位置
    return new Promise((resolve)=>{
      setTimeout(() => {
        resolve(savedPosition ? savedPosition : { left: 0, top: 0 });
      },1000)
    })
    // return savedPosition ? savedPosition : { left: 0, top: 0 };
  },
相关推荐
我要洋人死13 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人25 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人25 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR31 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香33 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969335 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai41 分钟前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風6 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#