初始化项目
npm init vite@latest
安装 router
yarn add vue-router
新建路由文件
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"
const routes: Array<RouteRecordRaw> = [
{
path: "/a", // 访问路径,在浏览器中使用 http://localhost:8080/a 就会访问 A组件
name: "A",
component: () => import("../components/A.vue") // 这里使用路由懒加载
},
{
path: "/b",
name: "B",
component: () => import("../components/B.vue")
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router
在 main.ts 导入路由文件
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router" // 引入路由文件
createApp(App).use(router).mount('#app')
app.vue
<template>
<div>
<div>
// router-link 渲染结果默认是 a标签,可用于路由跳转
<router-link class="a" to="/a">a</router-link>
<router-link class="b" to="/b">b</router-link>
</div>
// router-view 是router自带组件,必须使用。 访问 url 导入的路由组件,显示到 router-view 中。
<router-view></router-view>
</div>
</template>
<script setup lang="ts" ></script>
<style scoped>
</style>
router-link
可用于路由跳转
使用方式1
# 跳转 http://localhost/a
<router-link to="/a"></router-link>
使用方式2
# 跳转 http://localhost/a
# name对应的值是 路由配置中对应的 name值
<router-link :to="{ name: 'A'}"></router-link>
使用方式3(利用 js 实现)
<template>
<div>
<button @click="handleClick('/a')">按钮a</button>
<button @click="handleClick('/b')">按钮b</button>
<router-view></router-view>
</div>
</template>
<script setup lang="ts" >
import { useRouter } from "vue-router";
const router = useRouter();
const handleClick = (str: string) => {
// 方式1
router.push(str);
// 方式2
router.push({
path: str
})
// 方式3
router.push({
name: "A"
})
};
</script>
<style scoped>
</style>
使用 replace 浏览器不会产生历史记录
# 方式 1
<!-- **replace** 浏览器不会产生历史记录 -->
<router-link replace to="/a">按钮a</router-link>
# 方式2
<script setup lang="ts" >
import { useRouter } from "vue-router";
const router = useRouter();
const handleClick = (str: string) => {
// replace
router.replace("/a")
};
</script>
模拟浏览器的左右箭头
import { useRouter } from "vue-router";
const router = useRouter();
const handleClick = (str: string) => {
// 前进
router.go(1)
// 后退
router.back()
};
路由传参
方式1 query 传参
# url 会显示参数值 如:http://localhost:3000/#/a?name=hello+world
<script setup lang="ts" >
import { useRouter } from "vue-router";
const router = useRouter();
// 点击跳转 页面 并携带参数 { name: "hello world"}
const handleClick = () => {
router.push({
path: "/a",
query: {
name: "hello world"
}
})
}
</script>
// 对应页面,使用 useRoute 接收参数
<template>
<div>A
<div>{{router.query.name}}</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
const router = useRoute();
</script>
方式2 params传参
# url 不会显示参数值。注意:页面刷新,数据会丢失。
<script setup lang="ts" >
import { useRouter } from "vue-router";
const router = useRouter();
const handleClick = () => {
router.push({
name: "A",
params: {
name: "hello world"
}
})
}
// 对应页面,使用 useRoute 接收参数
<template>
<div>A
<div>{{router.params.name}}</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
const router = useRoute();
</script>
方式3 动态路由
# 路由文件 :name 动态参数
{
path: "/a/:name",
name: "A",
component: () => import("../components/A.vue")
},
# 跳转文件
<script setup lang="ts" >
import { useRouter } from "vue-router";
const router = useRouter();
const handleClick = () => {
router.push({
name: "A",
params: {
// name 必须和 路由文件的 :name一致
name: "hello world"
}
})
}
</script>
# 接收参数文件
<template>
<div>A
<div>{{router.params.name}}</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
const router = useRoute();
</script>
命名视图
const routes: Array<RouteRecordRaw> = [
{
path: "/",
component: () => import("../components/A.vue"),
children: [
{
path: "/user1",
components: {
default: () => import("../components/B.vue")
}
},
{
path: "/user2",
components: {
bbb: () => import("../components/B.vue"),
ddd: () => import("../components/D.vue"),
}
}
]
},
];
# App.vue
<template>
<div>
<router-view></router-view>
<router-view name="bbb"></router-view>
<router-view name="ddd"></router-view>
</div>
</template>
情况1:当访问 /user1 default 路由会渲染到 router-view 中
情况2:当访问 /user2。B.vue 和 D.vue 会分别渲染 到 name 为 bbb 和 ddd 的 router-view中
重定向
# 方式1
{
path: "/",
component: () => import("../components/A.vue"),
redirect: "/user1" // redirect 会重定向 到 /user1
}
#方式2 对象形式
{
path: "/",
component: () => import("../components/A.vue"),
redirect: {
name: "A" // 或 path: "/user1"
}
}
#方式3 函数形式
{
path: "/",
component: () => import("../components/A.vue"),
redirect: (to) => {
return "/user1"
}
}
#方式4 函数形式传参
{
path: "/",
component: () => import("../components/A.vue"),
redirect: (to) => {
return {
path: "/user1",
query: {
name: "hello world"
}
}
}
}
路由别名
{
path: "/",
component: () => import("../components/A.vue"),
alias: ["/root1", "/root2", "/root3"],
}
http://127.0.0.1/
http://127.0.0.1/root1
http://127.0.0.1/root2
以上路径都是 访问 A.vue组件
导航守卫
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router"
// 前置路由
// to 下一个路由地址
// form 从哪个路由跳转过来
// next 必须调用,否则无法跳转
router.beforeEach((to, form, next) => {
// 跳转的路径为 /regiset 则正常跳转,否则跳转到 /login 路径
if(to.path="/regiset") {
next()
} else {
next("/login")
}
})
// 后置路由(路由跳转)
router.afterEach((to, form) => {
})
createApp(App).use(router).mount('#app')
路由元信息
// 跳转不同 url 设置不同的标题
// 路由文件
{
path: "/",
component: () => import("../components/A.vue"),
meta: {
title: "首页"
}
}
// 在路由前置守卫设置 页面标题
router.beforeEach((to, form, next) => {
document.title = to.meta.title
})
滚动行为
const router = createRouter({
history: createWebHashHistory(),
scrollBehavior: (to, form, savePosition) => {
// savePosition 指定跳转的页面存在滚动条时,savePosition 才有值,并且记录当前页面滚动的位置 {left: 0, top: 8621}、
// 设置返回值为当前页面的滚动位置
if (savePosition) {
return savePosition
} else {
return {
top: 0
}
}
},
routes
});
// 同时支持 promise 对象
const router = createRouter({
history: createWebHashHistory(),
scrollBehavior: (to, form, savePosition) => {
// savePosition 指定跳转的页面存在滚动条时,savePosition 才有值,并且记录当前页面滚动的位置 {left: 0, top: 8621}、
// 设置返回值为当前页面的滚动位置
return new Promise((resolve) => {
setTimeout(() => {
resolve({
top: 200
})
}, 1000)
})
},
routes
});