vue3学习基础之vue-router

发布时间 2023-12-26 14:58:30作者: carol2014

我的vue3学习之路总是学学停停,最开始在18年开发微信小程序,就发现小程序和vue的语法有些相似,然后就去看了vue2的文档,随后忙其它的事情就丢下了。

直到22年又开始捡起来vue3,有了组合式api,语法简明很多,然后又不知道忙什么丢下。。。

前段有些空时间,就把vue3的学习整理下,使用vite构建结合element-plus做成了一个简单的网页应用,这里记录下。毕竟学为用

使用的命令:

# 搭建 vite 项目

npm init vite@latest

# 安装依赖

npm install

# 运行

npm run dev

# 安装其它组件

npm install vue-router@4

npm install pinia

npm install ant-design-vue@4.x --save
npm install -D unplugin-vue-components unplugin-auto-import

npm install element-plus --save

# 卸载不使用的安装包

npm uninstall ant-design-vue
npm rm ant-design-vue

 目录如下

整个网页应用使用vue-router路由

router.js

import {
  createRouter,
  createWebHashHistory,
  createWebHistory,
} from "vue-router";

// 定义一些路由,每个路由都需要映射到一个组件
const routes = [
  //命名路由、别名
  {
    path: "/",
    name: "home",
    component: () => import("./views/Home.vue"),
    alias: "/home",
  },

  //重定向
  { path: "/homePage", redirect: "/" },

  //嵌套路由
  {
    path: "/basic",
    children: [
      {
        path: "template",
        component: () => import("./views/basic/Template.vue"),
      },
      { path: "form", component: () => import("./views/basic/Form.vue") },
      { path: "event", component: () => import("./views/basic/Event.vue") },
      {
        path: "reactive",
        component: () => import("./views/basic/Reactive.vue"),
      },
    ],
  },
  {
    path: "/ad",
    children: [
      { path: "comp", component: () => import("./views/ad/Comp.vue") },
      { path: "use", component: () => import("./views/ad/Use.vue") },
    ],
  },

  {
    path: "/example",
    children: [
      {
        path: "table",
        component: () => import("./views/examples/SimpleTable.vue"),
      },
      { path: "tree", component: () => import("./views/examples/Tree.vue") },
      {
        path: "transition",
        component: () => import("./views/examples/Transition.vue"),
      },
      {
        path: "todo",
        component: () => import("./views/examples/todo.vue"),
      },
      {
        path: "crud",
        component: () => import("./views/examples/Crud.vue"),
      },
    ],
  },

  //带参数的动态路由匹配、路由组件传参
  {
    path: "/users/:username/posts/:postId",
    name: "users",
    component: () => import("./views/Test.vue"),
    props: true,
  },

  {
    path: "/router",
    children: [
      { path: "basic", component: () => import("./views/Router.vue") },
      //命名视图
      {
        path: "namedView",
        components: {
          default: () => import("./views/basic/Reactive.vue"),
          a: () => import("./views/basic/Event.vue"),
        },
      },
    ],
  },

  // 路由独享的守卫
  {
    path: "/pinia",
    component: () => import("./views/Pinia.vue"),
    meta: { requiresCamera: false, requiresAuth: true }, //路由元信息
    beforeEnter: (to, from) => {
      return true;
    },
  },
];

// 创建路由实例并传递 `routes` 配置
export const router = createRouter({
  // history: createWebHashHistory(), //Hash 模式 #
  history: createWebHistory(), //HTML5 模式
  routes,
});

 

 main.js

import { createApp } from "vue";
import App from "./App.vue";
import { router } from "./router";
import { createPinia } from "pinia";
import { useUserStore } from "./stores/user";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";

const pinia = createPinia();
const app = createApp(App);
app.config.errorHandler = (err) => {
  /* 处理错误 */
  console.log(err);
};
app.provide("api_url", "http://api.localhost.com/");

//使用pinia 管理全局状态
app.use(pinia);

//使用路由
app.use(router);

const userStore = useUserStore();
//全局前置守卫
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && to.name !== "Login" && !userStore.user_id) {
    next({ name: "Login" });
  } else {
    next();
  }
});

//全局解析守卫
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, failure) => {
  if (!failure) console.log(to.fullPath);
});

app.use(ElementPlus);

app.mount("#app");

 

App.vue

<script setup>
import { ref } from "vue";
import { useRouter, useRoute } from "vue-router";

const router = useRouter();
const route = useRoute();

const activeIndex = ref("/");
const handleSelect = (key, keyPath) => {
  router.push({
    path: key,
  });
  activeIndex.value = key;
};

router.push({
  path: "/",
});
</script>

<template>
  <div>
    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
      <el-menu-item index="/">Home</el-menu-item>

      <el-sub-menu index="basic">
        <template #title>基础知识应用</template>
        <el-menu-item index="/basic/template">模板语法</el-menu-item>
        <el-menu-item index="/basic/form">表单相关</el-menu-item>
        <el-menu-item index="/basic/event">事件绑定</el-menu-item>
        <el-menu-item index="/basic/reactive">响应式状态</el-menu-item>
      </el-sub-menu>

      <el-sub-menu index="ad">
        <template #title>进阶知识应用</template>
        <el-menu-item index="/ad/comp">组件</el-menu-item>
        <el-menu-item index="/ad/use">逻辑复用</el-menu-item>
      </el-sub-menu>

      <el-sub-menu index="router">
        <template #title>Vue-Router</template>
        <el-menu-item index="/router/basic">基础</el-menu-item>
        <el-menu-item index="/router/namedView">命名视图</el-menu-item>
      </el-sub-menu>

      <el-menu-item index="/pinia">Pinia</el-menu-item>

      <el-sub-menu index="example">
        <template #title>简单例子</template>
        <el-menu-item index="/example/table">table</el-menu-item>
        <el-menu-item index="/example/tree">tree</el-menu-item>
        <el-menu-item index="/example/transition">transition</el-menu-item>
        <el-menu-item index="/example/todo">todo</el-menu-item>
        <el-menu-item index="/example/crud">crud</el-menu-item>
      </el-sub-menu>

      <el-menu-item index="4" disabled>备用</el-menu-item>
    </el-menu>

    <!-- 路由出口,路由匹配到的组件将渲染在这里 -->
    <router-view></router-view>

    <!-- 命名视图 -->
    <router-view name="a"></router-view>
  </div>
</template>

<style scoped>
</style>

 

主菜单结合了element-plus,并未使用route-link标签,因此特意创建了views/Router.vue页面展示vue-router

<script setup>
</script>

<template>
  <div>
    <p>
      <!--使用 router-link 组件进行导航,通过传递 `to` 来指定链接 -->

      <router-link to="/basic/template">模板语法</router-link>
      <router-link to="/basic/form">表单相关</router-link>
      <router-link to="/basic/event">事件绑定</router-link>
      <router-link to="/basic/reactive">响应式状态</router-link>

      <router-link to="/ad/comp">组件</router-link>
      <router-link to="/ad/use">逻辑复用</router-link>

      <!-- 命名视图 -->
      <router-link to="/router/namedView">命名视图</router-link>

      <router-link to="/pinia">Pinia</router-link>

      <!-- 带参数的动态路由匹配 -->
      <router-link to="/users/eduardo/posts/1">/users/eduardo/posts/1</router-link>

      <!-- 命名路由 -->
      <router-link :to="{ name: 'users', params: { username: 'erina', postId: 2 } }">/users/erina/posts/2</router-link>
    </p>

    <div></div>
  </div>
</template>

<style scoped>
a {
  margin-left: 1rem;
}
</style>