目录
10 路由别名:不同路径渲染同一组件 Router- alias
前置知识
1.后退:
window.history.back() -- 相当于用户在浏览器的工具栏上点击返回按钮;
2.前进:
window.history.forward() -- 相当于用户在浏览器的工具栏上点击前进按钮;
3.移动到指定历史记录点:
通过go()方法,指定一个相对于当前页面位置的数值,从当前会话的历史记录中加载页面(当前位置页面索引:0,上一页:-1,下一页:1);
window.history.go(-2)--后退2页,相当于调用两次back();
window.history.go(1)--前进1页,相当于调用forward();
可以通过window.history.length,得到历史记录栈中一共有多少页。
window.onpopstate、
window.history.pushState、
window.history.replaceState API的区分
HTML5引入了 history.pushState() 和 history.replaceState() 方法,它们分别可以添加和修改历史记录条目。这些方法通常与window.onpopstate 配合使用
pushState() 方法
pushState() 需要三个参数: 一个状态对象, 一个标题 (目前被忽略), 和 (可选的) 一个URL. 让我们来解释下这三个参数详细内容:
1 状态对象可以是能被序列化的任何东西。原因在于Firefox将状态对象保存在用户的磁盘上,以便在用户重启浏览器时使用,我们规定了状态对象在序列化表示后有640k的大小限制。如果你给 pushState() 方法传了一个序列化后大于640k的状态对象,该方法会抛出异常。如果你需要更大的空间,建议使用 sessionStorage 以及 localStorage.
2 标题 — Firefox 目前忽略这个参数,但未来可能会用到。在此处传一个空字符串应该可以安全的防范未来这个方法的更改。或者,你可以为跳转的state传递一个短标题。
3 URL — 该参数定义了新的历史URL记录。注意,调用 pushState() 后浏览器并不会立即加载这个URL,但可能会在稍后某些情况下加载这个URL,比如在用户重新打开浏览器时。新URL不必须为绝对路径。如果新URL是相对路径,那么它将被作为相对于当前URL处理。新URL必须与当前URL同源,否则 pushState() 会抛出一个异常。该参数是可选的,缺省为当前URL。
replaceState() 方法
history.replaceState() 的使用与 history.pushState() 非常相似,区别在于 replaceState() 是修改了当前的历史记录项而不是新建一个。 注意这并不会阻止其在全局浏览器历史记录中创建一个新的历史记录项。
replaceState() 的使用场景在于为了响应用户操作,你想要更新状态对象state或者当前历史记录的URL。
popstate 事件
每当活动的历史记录项发生变化时, popstate 事件都会被传递给window对象。如果当前活动的历史记录项是被 pushState 创建的,或者是由 replaceState 改变的,那么 popstate 事件的状态属性 state 会包含一个当前历史记录状态对象的拷贝。
页面加载时,或许会有个非null的状态对象。这是有可能发生的,举个例子,假如页面(通过pushState() 或 replaceState() 方法)设置了状态对象而后用户重启了浏览器。那么当页面重新加载时,页面会接收一个onload事件,但没有 popstate 事件。然而,假如你读取了history.state属性,你将会得到如同popstate 被触发时能得到的状态对象。
1 为什么需要 Vue Router?
SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面;vue-router在实现单页面前端路由时,提供了两种方式:Hash模式和History模式;根据mode参数来决定采用哪一种方式。
这里的路由就是SPA(单页应用)的路径管理器
2 一个不用 Vue Router 的例子
<template>
<nav>
<a
v-for="(route, path) in routes"
:href="path"
@click.prevent="changeRoute(path)"
>{
{ route.label }}</a
>
</nav>
<component :is="currentPage" />
</template>
<script setup>
import PageOne from "./components/PageOne.vue";
import PageTwo from "./components/PageTwo.vue";
import PageThree from "./components/PageThree.vue";
import { ref, computed } from "vue";
const routes = {
"/": {
component: PageOne,
label: "页面1",
},
"/2": {
component: PageTwo,
label: "页面2",
},
"/3": {
component: PageThree,
label: "页面3",
},
};
const currentPath = ref(location.pathname);
const currentPage = computed(
() => routes[currentPath.value].component || PageOne
);
function changeRoute(path) {
history.pushState(null, null, path);
currentPath.value = location.pathname;
}
</script>
3 Vue Router 安装和入门
1 yarn add vue-router@4
2 新建配置文件 router.js
router.js
import PageOne from "./components/PageOne.vue";
import PageTwo from "./components/PageTwo.vue";
import PageThree from "./components/PageThree.vue";
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{
path: "/",
component: PageOne,
},
{
path: "/2",
component: PageTwo,
},
{
path: "/3",
component: PageThree,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./routes"; //引入vue router
const app = createApp(App);
app.use(router); //使用router
app.mount("#app");
App.vue
<router-link to="/">页面1</router-link>
<router-view></router-view>
<template>
<nav>
<router-link to="/">页面1</router-link>
<router-link to="/2">页面2</router-link>
<router-link to="/3">页面3</router-link>
</nav>
<router-view></router-view>
</template>
<script>
export default {};
</script>
通过 <router-link>
标签中的to传参
<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>
4 嵌套路由:实现页面子组件切换
文件目录:
更新配置: 嵌套路由
const routes = [
{
path: "/",
component: HomePage,
},
{
path: "/about",
component: AboutMe,
children: [
{ path: "work", component: WorkExperience },
{ path: "education", component: EducationExperience },
],
},
];
页面:
App.vue
<template>
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</nav>
<router-view></router-view>
</template>
AboutMe.vue
<template>
<div class="container">
<p>Hi 你好!这是关于我的页面</p>
<p>更多详情查看:</p>
<nav>
<router-link to="/about/work">工作经历</router-link>
<router-link to="/about/education">教育经历</router-link>
</nav>
<router-view></router-view>
</div>
</template>
5 动态路由匹配和参数获取
配置:
const routes = [
{
path: "/",
component: BlogListPage,
},
{
path: "/:postId",
component: BlogPostPage,
},
];
BlogListPage.vue
<template>
<main>
<div className="blogPosts">
<article v-for="blogPost in blogPosts" :key="blogPost.id">
<h2>
<router-link :to="`/${blogPost.id}`">{
{
blogPost.title
}}</router-link>
</h2>
<p>{
{ blogPost.body.substring(0, 100) + "..." }}</p>
</article>
</div>
</main>
</template>
<script>
import { getAllPosts } from "../data/blogPosts";
blogPosts.vue
blogPosts.vue
<template>
<article>
<h2>
{
{ blogPost.title }}
</h2>
<p>{
{ blogPost.body }}</p>
<footer>
<router-link to="/">回到主页</router-link>
</footer>
</article>
</template>
<script>
export default {
data() {
return { blogPost: {} };
},
created() {
this.blogPost = getBlogPostById(this.$route.params.postId);
},
};
export function getBlogPostById(id) {
return blogPosts.find((post) => post.id === Number(id));
}
</script>