(九)Vue3-huohuo-admin src构建-下

494 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

这里我们继续构建src。

plugins 项目插件配置

这里主要是引入一些开发中需要用到的插件,并进行自定义配置,比如EChartsElement-PlusVxe-tablei18n...

Element-Plus 举例

本项目我们使用Element-Plus作为主要的 UI 组件框架。

由于Vue 3不再支持IE11Element Plus也不再支持IE浏览器

image-20220513113130295

这里我们先安装

pnpm install element-plus

以前组件我们都是按需导入,目前官网推荐我们安装几款插件来支持按需导入,你可能要依赖插件手动导入样式,还可能要手动加载非组件模块(比如ELMessage)。这种方式不仅在开发上带来许多麻烦,还会影响Vite热重载的速度,让你打开页面会更慢,所以我们使用全局引入的方式(期待有更好的解决方案吧!)。

引入

// main.ts
import App from "./App.vue";
import { createApp } from "vue";
import ElementPlus from "element-plus";

import "element-plus/dist/index.css";

const app = createApp(App);

app.use(ElementPlus);
app.mount("#app");

使用

image-20220513145228791

关于element-plus有一个地方需要注意:element-plus默认语言为英文,使用一些组件时(如分页组件)会发现默认字体是英文,这时候我们需要转换为英文。

element-plus默认语言改为中文

<!-- App.vue -->
<template>
  <el-config-provider :locale="currentLocale">
    <router-view />
  </el-config-provider>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { ElConfigProvider } from "element-plus";

import zhCn from "element-plus/lib/locale/lang/zh-cn";

export default defineComponent({
  name: "app",
  components: {
    [ElConfigProvider.name]: ElConfigProvider,
  },
  data() {
    return {
      currentLocale: zhCn,
    };
  },
});
</script>

当然如果你想做国际化,如中英文切换,只需要将英文也引入,使用计算属性来实现。

<!-- App.vue -->
<template>
  <el-config-provider :locale="currentLocale">
    <router-view />
  </el-config-provider>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { ElConfigProvider } from "element-plus";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import en from "element-plus/lib/locale/lang/en";
export default defineComponent({
  name: "app",
  components: {
    [ElConfigProvider.name]: ElConfigProvider,
  },
  computed: {
    currentLocale() {
      return this.$storage.locale?.locale === "zh" ? zhCn : en;
    },
  },
});
</script>

router 项目路由

我们采用Vue.js官方路由 Vue-Router来创建单页应用,将我们的组件都映射到路由上。

引入 Vue-router

安装

pnpm install vue-router

定义路由

首先创建我们的路由文件夹router,并为该文件夹提供一个出口文件index.ts。项目所有的路由都采用模块化管理(不同的业务流或者页面模块分别在各自的页面中配置路由)。

image-20220513160702801

路由出口

我们使用router-view来将路由匹配到的组件进行渲染,放在我们的根组件(App.vue)下,

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

<script setup lang="ts"></script>

配置基础 router

我们先创建一个单文件组件example.vue(放在src目录下创建的views页面文件中)

<!-- 测试案例 -->
<script setup lang="ts"></script>

<template>
  <h1>example...</h1>
</template>

<style scoped></style>

建立路由与组件的映射

// src\router\modules\example.ts
const exampleRouter = {
  path: "/example", // 当前组件的url地址
  component: () => import("/@/views/example.vue"), // 按需引入组件
};

export default exampleRouter; // 记得默认导出

配置基本 router

// src\router\index.ts
import { createRouter, createWebHistory, Router } from "vue-router";

import exampleRouter from "./modules/example"; // 引入路由模块

const routes = [exampleRouter];

// 创建路由实例
export const router: Router = createRouter({
  history: createWebHistory(), // 使用 hash 模式
  routes: routes, // 传入我们所有的路由
  strict: true, // 开启严格模式
});

export default router; // 导出我们的路由

引入项目中

// main.ts
import App from "./App.vue";
import router from "./router"; // 引入
import { createApp } from "vue";
import ElementPlus from "element-plus";

import "element-plus/dist/index.css";

const app = createApp(App);
// 确保整个应用支持路由
app.use(router).use(ElementPlus);
app.mount("#app");

效果示例

image-20220513161831497

store 状态管理

状态管理我们不再使用以前常用的Vuex,而是使用 Pinia(PS:pinia官网的代码字体,属实是爱的不能再爱了,太好看了叭!),我们看看Pinia的优势:

  • 提供了Composition-API风格的API
  • 完整可靠的TypeScript支持
  • mutations移除,action被调度为常规函数使用
  • 极其轻巧(体积约 1KB)
  • 支持多个Store
  • 支持Vue devtoolsSSR渲染

安装

pnpm install pinia

store文件结构跟router 一样

image-20220513172807448

配置并引入

创建我们的pinia出口

// src\store\index.ts
import type { App } from "vue";
import { createPinia } from "pinia";
const store = createPinia();

export function setupStore(app: App<Element>) {
  app.use(store);
}

export { store };

引入

// src\main.ts
import App from "./App.vue";
import router from "./router";
import { setupStore } from "/@/store"; // 引入
import { createApp } from "vue";
import ElementPlus from "element-plus";

import "element-plus/dist/index.css";

const app = createApp(App);
setupStore(app); // Configure store
app.use(router).use(ElementPlus);
app.mount("#app");

使用举例

// src\store\modules\example.ts
import { store } from "/@/store";
import { defineStore } from "pinia";

export const useTestStore = defineStore({
  id: "huohuo-test", // 为当前store命名唯一id
  state: () => ({
    // store中存放的数据
    msg: "I am HuoHuo!",
  }),
  getters: {
    getMsg() {
      return this.msg;
    },
  },
  actions: {
    // 操作store中数据的方法
    handleMsg(val) {
      this.msg = val;
    },
  },
});

// 以函数的形式返回
export function useTestStoreHook() {
  return useTestStore(store);
}
<!-- 测试案例 -->
<script setup lang="ts">
import { ref } from "vue";
import { useTestStoreHook } from "/@/store/modules/example";

const message = ref("Hello HuoHuo");
function useMsg() {
  message.value = useTestStoreHook().msg;
}
function changeMsg() {
  useTestStoreHook().handleMsg("你好啊!");
}
</script>

<template>
  <h1>example...</h1>
  <h2>{{ message }}</h2>
  <el-button @click="useMsg">测试store的msg</el-button>
  <el-button @click="changeMsg">测试store的handleMsg</el-button>
</template>

<style scoped></style>

案例效果展示

image-20220513180143923

style 样式库

我们的CSS采用Sass来支持,因为我们使用的 Element-Plus 也是使用的Sass,我们保持一致性。项目的大部分样式都放在这里,包括CSS初始化文件、插件样式更改文件、自定义样式等。

Sass 安装

pnpm install sass -D

我们在src根目录下建立style样式文件,并初始化一些 CSS

// src\style\index.scss
body {
  width: 100%;
  height: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizelegibility;
  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
    "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}

html {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

#app {
  width: 100%;
  height: 100%;
}

引入 Windi CSS

写样式是一件比较费时间的事情,所以这里我们使用Windi CSS这个CSS框架工具,它既能够在开发中让我们十分便捷地写CSS,又能提供更快的加载体验和更快的HMR,而且,它是基于TS开发的!

在 Vite 中集成

安装

pnpm install -D vite-plugin-windicss windicss

使用这个插件时,记得在VSCode中安装该插件的扩展WindiCSS IntelliSense,能够在开发中给你非常友好的提示。

引入

image-20220516211649857

使用

如何使用Windi CSS,可以看它的工具类指令

image-20220516212438654

自定义配置

我们需要在根目录下创建一个windi.config.ts文件,进行配置(个性化配置较多,大家可自行上官网查阅相关示例)。

import { defineConfig } from "windicss/helpers";

export default defineConfig({
  /* 配置项... */
});

scoped

vue文件中编写style样式时,记得添加scoped属性,如果没有加,默认会被编译成全局样式,可能会造成全局样式污染。

<style scoped></style>

使用scoped后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的scoped CSS和子组件的scoped CSS的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。

utils 方法库

一个存放着整个项目中使用到的具有一定功能性的工具方法的库,方便统一管理我们封装的方法。

App.vue

项目的根组件,是页面的入口文件,实际上所有的单页面都在该页面下进行切换。一般来说,我们会在这里配置项目路由的入口、项目全局的配置、国际化等功能。

main.ts

项目应用的入口文件,项目所有的插件或依赖都从这里引进,始终服务于后面的开发。