Vue3 系列:vue-router

简介: Vue3 系列:vue-router

vue-router 版本为4的是为vue3准备的

如果是vue2 安装版本为vue-router@3

1. 基础用法

// router -> index.js
import { createRouter, createWebHistory } from "vue-router";
 
let router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/login",
      name: "login",
      component: () => import("@/views/login.vue"),
    },
  ],
  scrollBehavior() {
    return {
      el: "#app",
      top: 0,
      behavior: "smooth",
    };
  },
});
 
export default router;
 
// main.js
import router from "./router/index.js";
const app = createApp(App);
app.use(router);
 
// App.vue 
<router-view></router-view>;

2. 路由跳转

<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
import { useRouter } from "vue-router";
let router = useRouter();
 
// 字符串路径
router.push("/users/eduardo");
 
// 带有路径的对象
router.push({ path: "/users/eduardo" });
 
// 命名的路由,并加上参数,让路由建立 url
router.push({ name: "user", params: { username: "eduardo" } });
 
// 带查询参数,结果是 /register?plan=private
router.push({ path: "/register", query: { plan: "private" } });
 
// 带 hash,结果是 /about#team
router.push({ path: "/about", hash: "#team" });
 
// 注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path
const username = "eduardo";
// 我们可以手动建立 url,但我们必须自己处理编码
router.push(`/user/${username}`); // -> /user/eduardo
// 同样
router.push({ path: `/user/${username}` }); // -> /user/eduardo
// 如果可能的话,使用 `name` 和 `params` 从自动 URL 编码中获益
router.push({ name: "user", params: { username } }); // -> /user/eduardo
// `params` 不能与 `path` 一起使用
router.push({ path: "/user", params: { username } }); // -> /user
```

3. 动态路由

// router->index.js
const routes = [{ path: "/user/:id", component: User }];
 
// User组件 获取参数 url: user/1
import { useRoute } from "vue-router";
let route = useRoute();
console.log(route.params); // { id: 1 }
<!-- template 中获取url参数 -->
{{ $route.params }}

4. 嵌套路由

const routes = [
  {
    path: "/user/:id",
    component: User,
    children: [
      {
        // 当 /user/:id/profile 匹配成功
        // UserProfile 将被渲染到 User 的 <router-view> 内部
        path: "profile",
        component: UserProfile,
      },
      {
        // 当 /user/:id/posts 匹配成功
        // UserPosts 将被渲染到 User 的 <router-view> 内部
        path: "posts",
        component: UserPosts,
      },
    ],
  },
];

5. 命名路由

// 除了 path 之外,你还可以为任何路由提供 name
const routes = [
  {
    path: "/user/:username",
    name: "user",
    component: User,
  },
];

6. 命名视图

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: "/",
      components: {
        default: Home,
        // LeftSidebar: LeftSidebar 的缩写
        LeftSidebar,
        // 它们与 `<router-view>` 上的 `name` 属性匹配
        RightSidebar,
      },
    },
  ],
});
<router-view class="view left-sidebar" name="LeftSidebar"></router-view>
<router-view class="view main-content"></router-view>
<router-view class="view right-sidebar" name="RightSidebar"></router-view>

7. 重定向

const routes = [{ path: "/home", redirect: "/" }];
const routes = [{ path: "/home", redirect: { name: "homepage" } }];
const routes = [
  {
    // /search/screens -> /search?q=screens
    path: "/search/:searchText",
    redirect: (to) => {
      // 方法接收目标路由作为参数
      // return 重定向的字符串路径/路径对象
      return { path: "/search", query: { q: to.params.searchText } };
    },
  },
  {
    path: "/search",
    // ...
  },
];
const routes = [
  {
    // 将总是把/users/123/posts重定向到/users/123/profile。
    path: "/users/:id/posts",
    redirect: (to) => {
      // 该函数接收目标路由作为参数
      // 相对位置不以`/`开头
      // 或 { path: 'profile'}
      return "profile";
    },
  },
];

8. 别名

// 当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /
const routes = [{ path: "/", component: Homepage, alias: "/home" }];

9. 路由组件传参

const User = {
  // 请确保添加一个与路由参数完全相同的 prop 名
  props: ["id"],
  template: "<div>User {{ id }}</div>",
};
const routes = [{ path: "/user/:id", component: User, props: true }];
 
// 有命名视图得路由
const routes = [
  {
    path: "/user/:id",
    components: { default: User, sidebar: Sidebar },
    props: { default: true, sidebar: false },
  },
];

10. 导航守卫

const router = createRouter({ ... })
router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false
})
// false: 取消当前的导航。
// 一个路由地址: 通过一个路由地址跳转到一个不同的地址。
// 如果什么都没有,undefined 或返回 true,则导航是有效的
router.beforeEach(async (to, from) => {
  if (
    // 检查用户是否已登录
    !isAuthenticated &&
    // ❗️ 避免无限重定向
    to.name !== "Login"
  ) {
    // 将用户重定向到登录页面
    return { name: "Login" };
  }
});
// 全局解析守卫, 确保用户可以访问自定义 meta 属性
router.beforeResolve(async (to) => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission();
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... 处理错误,然后取消导航
        return false;
      } else {
        // 意料之外的错误,取消导航并把错误传给全局处理器
        throw error;
      }
    }
  }
});
// 全局后置钩子,它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用
router.afterEach((to, from) => {
  sendToAnalytics(to.fullPath);
});

11. 路由元信息

// 有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等,并且它可以在路由地址和导航守卫上都被访问到
const routes = [
  {
    path: '/posts',
    component: PostsLayout,
    children: [
      {
        path: 'new',
        component: PostsNew,
        // 只有经过身份验证的用户才能创建帖子
        meta: { requiresAuth: true }
      },
      {
        path: ':id',
        component: PostsDetail
        // 任何人都可以阅读文章
        meta: { requiresAuth: false }
      }
    ]
  }
]
 
router.beforeEach((to, from) => {
  // 而不是去检查每条路由记录
  // to.matched.some(record => record.meta.requiresAuth)
  if (to.meta.requiresAuth && !auth.isLoggedIn()) {
    // 此路由需要授权,请检查是否已登录
    // 如果没有,则重定向到登录页面
    return {
      path: '/login',
      // 保存我们所在的位置,以便以后再来
      query: { redirect: to.fullPath },
    }
  }
})

12. 过渡效果

const routes = [
  {
    path: "/custom-transition",
    component: PanelLeft,
    meta: { transition: "slide-left" },
  },
  {
    path: "/other-transition",
    component: PanelRight,
    meta: { transition: "slide-right" },
  },
];
<router-view v-slot="{ Component, route }">
  <!-- 使用任何自定义过渡和回退到 `fade` -->
  <transition :name="route.meta.transition || 'fade'">
    <component :is="Component" />
  </transition>
</router-view>
/*
  进入和离开动画可以使用不同
  持续时间和速度曲线。
*/
.slide-left-enter-active {
  transition: all 0.3s ease-out;
}
 
.slide-left-leave-active {
  transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
 
.slide-left-enter-from,
.slide-left-leave-to {
  transform: translateX(20px);
  opacity: 0;
}
 
/* 动画 */
.slide-left-enter-active {
  animation: bounce-in 0.5s;
}
.slide-left-leave-active {
  animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}

13. 滚动行为

const router = createRouter({
  history: createWebHashHistory(),
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置
  }
})
 
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终滚动到顶部
    return { top: 0 }
  },
})
 
// 你也可以通过 el 传递一个 CSS 选择器或一个 DOM 元素。在这种情况下,top 和 left 将被视为该元素的相对偏移量。
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终在元素 #main 上方滚动 10px
    return {
      // 也可以这么写
      // el: document.getElementById('main'),
      el: '#main',
      top: -10,
    }
  },
})
 
// 如果你的浏览器支持滚动行为,你可以让它变得更流畅
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return {
        el: to.hash,
        behavior: 'smooth',
      }
    }
  }
})


目录
相关文章
|
1天前
|
JavaScript
vue项目中使用vue-router进行路由配置及嵌套多级路由
该文章详细说明了如何在Vue项目中配置和使用vue-router进行单页面应用的路由管理,包括设置嵌套路由和实现多级路由导航的示例。
vue项目中使用vue-router进行路由配置及嵌套多级路由
|
2天前
|
JavaScript
在 Vue 3 组件通信方式中,Provide / Inject 与 Vuex 的区别是什么?
在 Vue 3 组件通信方式中,Provide / Inject 与 Vuex 的区别是什么?
|
2天前
|
存储 JavaScript
Vue 3 组件通信方式
Vue 3 组件通信方式
|
1天前
|
JavaScript 前端开发 API
vue3的传送门teleport究竟有多神奇?suspense发起异步请求有多简约?
该文章介绍了Vue3中新特性Teleport和Suspense的使用方法,演示了如何使用Teleport进行DOM节点的非父子关系传送,以及Suspense在处理异步组件加载时的优雅展示和错误处理技巧。
|
1天前
|
JavaScript
particles 粒子背景插件在vue3中的使用
本文介绍了如何在Vue 3项目中使用`particles.vue3`库来创建粒子背景特效。文章提供了粒子背景插件的概述、安装步骤、配置参数说明,并展示了粒子特效的实现效果。同时,提供了在main.js中进行全局配置、在Vue组件中使用粒子背景组件的示例代码,以及完整代码的下载链接。
|
1天前
|
缓存 JavaScript 算法
卷不动也得继续学!紧跟vue3的步伐,再来get一波进阶新特性!
该文章深入讲解了Vue3的进阶新特性,包括`watchEffect`的使用、性能优化策略、Vite构建工具的优势以及全局API的变化等内容,帮助开发者更好地掌握Vue3的开发技巧。
卷不动也得继续学!紧跟vue3的步伐,再来get一波进阶新特性!
|
1天前
vue2的响应式原理学“废”了吗?继续观摩vue3响应式原理Proxy
该文章对比了Vue2与Vue3在响应式原理上的不同,重点介绍了Vue3如何利用Proxy替代Object.defineProperty来实现更高效的数据响应机制,并探讨了这种方式带来的优势与挑战。
vue2的响应式原理学“废”了吗?继续观摩vue3响应式原理Proxy
|
1天前
|
缓存 移动开发 JavaScript
查漏补缺方为上策!!两万六字总结vue的基本使用和高级特性,周边插件vuex和vue-router任你挑选
该文章全面总结了Vue.js的基本使用方法与高级特性,并介绍了Vue周边的重要插件Vuex和Vue-Router的使用技巧。
查漏补缺方为上策!!两万六字总结vue的基本使用和高级特性,周边插件vuex和vue-router任你挑选
|
1天前
|
JavaScript 前端开发 UED
组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList
该文章详细介绍了如何使用Vue3结合TypeScript来开发全局Header组件和列表数据渲染组件ColumnList,并提供了从设计到实现的完整步骤指导。
|
1天前
|
JavaScript API
模块化妙用!用vue3实现一个鼠标追踪器和异步加载组件
该文章展示了如何使用Vue3的Composition API实现鼠标追踪器功能,并介绍了创建异步加载组件的方法,利用TS泛型增强了组件的灵活性与可维护性。