1、Router
一、URL 的hash 改变路由原理
URL的hash也就是锚点(#),本质上是改变window.location的href属性
可以通过直接复制location.hash来改变href,但是页面不发生刷新
<div id="app">
<a href="#/home">home</a>
<a href="#/about">about</a>
<div class="content">Default</div>
</div>
<script>
const contentEl = document.querySelector(".content");
window.addEventListener("hashchange", () => {
switch(location.hash) {
case "#/home":
contentEl.innerHTML = "home";
break;
case "#/about":
contentEl.innerHTML = "about";
break;
default:
contentEl.innerHTML = "default";
}
})
</script>
二、URL 的history 改变路由原理
history 接口是HTML5新增的,它有六种模式改变URL而不刷新页面
- replaceState:替换原来的路径
- pushState:使用新的路径
- popState:路径的回退
- go:向前或向后改变路径
- forward:向前改变路径
- back:向后改变路径
<div id="app">
<a href="/home">home</a>
<a href="/about">about</a>
<div class="content">Default</div>
</div>
<script>
const contentEl = document.querySelector(".content");
const aEls = document.getElementsByTagName("a");
for(let aEl of aEls) {
aEl.addEventListener("click", e => {
e.preventDefault();
const href = aEl.getAttribute("href");
history.pushState({},"",href);
switch(location.pathname) {
case "/home":
contentEl.innerHTML = "home";
break;
case "/about":
contentEl.innerHTML = "about";
break;
default:
contentEl.innerHtml = "Default";
}
})
}
</script>
三、路由的基本使用
// App.vue
<template>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="about">关于</router-link>
<router-view/>
</div>
</template>
// router.js
import { createRouter, createWebHistory, createrWebHashHistory } from 'vue-router'
import Home from '../pages/Home.vue';
import About from '../pages/About.vue';
// 配置映射关系 routes
const routes = [
{ path: "/", redirect: "/home" },
{ path: "/home", component: Home },
{ path: "/about", component: About }
];
// 创建路由对象 router
const router = createRouter({
routes,
history: createrWebHashHistory(),
// history: createWebHistory()
})
export default router
// main.js
import { createApp } from 'vue';
import router from './router';
import App from './App.vue';
const app = createApp(App);
app.use(router);
app.mount("#app");
四、router-link 的属性
- to:只是一个字符串,或者是一个对象
- replace:当点击时,会调用router.replace(),而不是router.push()
- active-class:设置激活a元素后应用的class,默认是router-link-active
- exace-active-class:精准匹配,链接精准激活时,应用于渲染的<a>的class,默认是router-link-exact-active
<template>
<div id="app">
<router-link to="/home" replace active-class="why-active">首页</router-link>
<router-link to="/about" replace active-class="why-active">关于</router-link>
<router-view/>
</div>
</template>
<style scoped>
.router-link-active {
color: red
}
.why-active {
color: blue
}
</style>
// router.js
// 修改active-class 和 exace-active-class
const router = createRouter({
routes,
history: createWebHistory(),
linkActiveClass: "why-active",
linkExactActiveClass: "thy-exact-active"
})
五、路由懒加载
import { createRouter, createWebHistory, createrWebHashHistory } from 'vue-router'
// 配置映射关系 routes
const routes = [
{ path: "/", redirect: "/home" },
// 路由懒加载
// import 返回的是一个promise
// 在打包的时候会对静态资源自动分包
// magic comment webpack魔法注释 修改打包后的文件名称
{ path: "/home", component: () => import ( /* webpackChunkName: "home-chunk" */"../pages/Home.vue" )},
{ path: "/about", component: () => import ( /* webpackChunkName: "about-chunk" */"../pages/About.vue" )}
];
// 创建路由对象 router
const router = createRouter({
routes,
history: createrWebHashHistory(),
// history: createWebHistory()
})
export default router
六、路由的其他属性
const routes = [
{ path: "/", redirect: "/home" },
{
path: "/home",
component: "home",
// 路由记录独一无二的名称
name: "home",
// 自定义数据
meta: {
name: "why",
age: 18,
height: 1.88
}
}
];
七、动态路由匹配
// router.js
import { createRouter, createWebHistory, createrWebHashHistory } from 'vue-router'
import Home from "../pages/Home.vue";
import About from "../pages/About.vue";
import User from "../pages/User.vue"
// 配置映射关系 routes
const routes = [
{ path: "/", redirect: "/home" },
{
path: "/home",
component: Home,
},
{
path: "/about",
component: About,
},
{
path: "/user/:username/id/:id",
component: User,
}
];
// 创建路由对象 router
const router = createRouter({
routes,
history: createWebHistory(),
// history: createrWebHashHistory(),
})
export default router
// App.vue
<template>
<div id="app">
<router-link to="/home" >首页</router-link>
<router-link to="/about" >关于</router-link>
<router-link :to="'/user' + name + 'id' + id">关于</router-link>
<router-view/>
</div>
</template>
<script>
export default {
data() {
return {
name: why,
id: 111
}
},
}
</script>
// User.vue
<template>
<div>
<h2>User: {{ $route.params.username }} - {{ $route.params.id }}</h2>
</div>
</template>
<script>
import { useRoute } from "vue-router"
export default {
created() {
console.log(this.$route.params.username)
},
setup() {
const route = useRoute();
console.log(route.params.username)
}
}
</script>
八、NotFound 的匹配路由
// NotFound.Vue
<template>
<div>
<h2>Page Not Found</h2>
<h1>{{ $route.params.patchMatch }}</h1>
</div>
</template>
// router.js
import { createRouter, createWebHistory, createrWebHashHistory } from 'vue-router'
import Home from "../pages/Home.vue";
import About from "../pages/About.vue";
// 配置映射关系 routes
const routes = [
{ path: "/", redirect: "/home" },
{
path: "/home",
component: Home,
},
{
path: "/about",
component: About,
},
{
path: "/:pathMatch(.*)*",
component: () => import("../pages/NotFound.vue")
}
];
// 创建路由对象 router
const router = createRouter({
routes,
history: createWebHistory(),
// history: createrWebHashHistory(),
})
export default router
九、路由嵌套
// Home.vue
<template>
<div>
<h2>Home</h2>
<router-link to="/home/message">消息</router-link>
<router-link to="/home/shops">商品</router-link>
<router-view></router-view>
</div>
</template>
// router.js
import { createRouter, createWebHistory, createrWebHashHistory } from 'vue-router'
import Home from "../pages/Home.vue";
import About from "../pages/About.vue";
// 配置映射关系 routes
const routes = [
{ path: "/", redirect: "/home" },
{
path: "/home",
component: Home,
children: [
{
path: "",
redirect: "/home/message"
},
{
path: "message",
component: () => import("../pages/HomeMessage.vue")
},
{
path: "shops",
component: () => import("../pages/HomeShops.vue")
}
]
},
{
path: "/about",
component: About,
},
];
// 创建路由对象 router
const router = createRouter({
routes,
history: createWebHistory(),
// history: createrWebHashHistory(),
})
export default router
十、编程式导航
// App.vue
<template>
<div id="app">
<router-link to="/home" >首页</router-link>
<router-link to="/about" >关于</router-link>
<button @click="jumpToAbout">跳转到关于</button>
<button @click="forwardOneStep">前进一步</button>
<router-view/>
</div>
</template>
<script>
import { useRouter } from 'vue-router'
export default {
// Vue2
methods: {
jumpToHome() {
this.$router.push("/about")
}
},
// Vue3
setup() {
const router = useRouter()
const jumpToAbout = () => {
// router.push("/about")
// 通过query 方式传递参数
router.push({
path: "/about",
query: {
name: "why",
age: 18
}
})
}
const forwardOneStep = () => {
router.replace("/about")
router.go(1);
router.go(-1);
router.forward();
router.back();
}
return {
jumpToAbout,
forwardOneStep
}
}
}
</script>
// About.vue
<template>
<div>
<h2>关于 {{ $route.query.name }} - {{ $route.query.age }}</h2>
</div>
</template>
十一、router-link 的v-slot
<template>
<div id="app">
<!-- props: href 跳转的链接 -->
<!-- props: route 对象 -->
<!-- props: navigate 导航函数 -->
<!-- props: isActive 是否当前处于活跃的状态 -->
<!-- props: isExactActive 是否当前处于精确的活跃的状态 -->
<router-link to="/home" v-slot="props" custom>
<p>{{ props.route }}</p>
<button>{{ props.href }}</button>
<button @click="props.navigate">哈哈哈</button>
<span :class="{'active': props.isActive}">{{ props.isActive }}</span>
<span :class="{'active': props.isExactActive}">{{ props.isExactActive }}</span>
</router-link>
<router-view/>
</div>
</template>
十二、