Skip to content

5.2 设计:搭建项目的基础结构

在确认需求之后,就要动手搭建应用框架。首先使用脚手架生成默认项目,然后在此基础上添加需要的配置。

5.2.1 使用脚手架创建项目

打开命令行工具,先切换到存储项目的文件夹,再执行以下命令:

sh
$ npm create vue@3

使用此命令不仅会拉取 Vue.js 3 项目模板,还会在终端提示用户选择生成项目的选项。可供选择的选项如下。

  • 项目名称:vue3-memo。
  • 选择集成的包:TypeScript、JSX、Vue Router 和 Pinia。

稍等几分钟,终端会提示项目创建成功。

先使用 VSCode 编辑器打开项目,再在该编辑器的终端执行以下命令安装依赖:

sh
$ yarn && yarn run start

安装依赖后会自动运行项目。运行成功后,打开浏览器即可看到项目默认的页面。

5.2.2 接入 UI 框架 Element Plus

得益于前端的快速发展,以及组件的高度标准化,很多基础页面内容不需要从 0 开始编写,可以选择一个好用且功能强大的 UI 框架迅速开发页面。

Element Plus 是 Element UI 的 Vue.js 3 升级版,组件丰富,应用范围广,社区也有很多的案例,是非常优秀的解决方案。接下来安装并使用 Element Plus。

(1)在项目目录下使用 yarn 命令安装 Element Plus:

sh
$ yarn add element-plus

(2)在入口文件 main.ts 中全局注册 Element Plus:

js
// main.ts
import ElementPlus from "element-plus";
import "./styles/main.less";
app.use(ElementPlus);

在上述代码中引入了全局样式 styles/main.less。在默认情况下,用 Vue.js 3 创建的项目不支持 Less,所以还需要安装 Less 模块:

sh
$ yarn add less

在安装 Less 模块之后,Vue.js 3 即可自动解析 Less 语法。

(3)创建 main.less 文件,并在头部直接引入 Element Plus 的样式:

js
// main.less
@import 'element-plus/dist/index.css';

(4)在 App.vue 中添加一个 Element Plus 的按钮组件:

js
<el-button type="primary">按钮</el-button>

(5)通过在终端执行 yarn dev 命令启动项目,可以发现 Element Plus 组件生效。

5.2.3 使用 Vue Router 配置页面路由

前端路由系统是由“一个根组件 + 多个配置组件”组成的。根组件是 App.vue,在入口文件中可以直接渲染这个组件。而配置组件则是在 Vue Router 中配置的,这些组件都有一个特定的路由地址,在访问这些地址时,地址匹配的组件就会被渲染到屏幕上。

接下来基于首页和登录页配置页面路由。

(1)在 views 文件夹下新建两个组件,分别是 Home.vue 和 Login.vue。这两个组件分别代表项目的首页和登录页(注意:首字母要用大写形式)。

(2)先创建 router/index.ts 文件,再创建路由对象。

目录 router 是路由目录,router/index.ts 是路由入口文件。在这个文件中,不仅要创建全局路由对象,还要为页面添加路由配置,代码如下:

js
import { createRouter, createWebHistory } from "vue-router";
import HomeView from "@/views/Home.vue";
import LoginView from "@/views/Login.vue";

const router = createRouter({
  history: createWebHistory(), // 不带“#”的路由模式
  routes: [
    { path: "/", component: HomeView },
    { path: "/login", component: LoginView },
  ],
});
export default router;

上面的代码为首页和登录页配置了一级路由。当在浏览器中访问这些配置好的 path 时,就能匹配到对应的组件。

(3)将创建好的路由对象导入入口文件 main.ts,并在 Vue.js 实例中注册:

js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
const app = createApp(App);
app.use(router);

(4)将根组件 App.vue 的代码修改为如下形式:

vue
<template>
  <router-view />
</template>

<script setup lang="ts">
import { RouterView } from "vue-router";
</script>

根组件只需要一个 <router-view /> 渲染容器。当一级路由匹配到某个组件时,该组件就会被渲染到这里。

5.2.4 使用 Pinia 做全局状态管理

在传统的 Vue.js 组件编写方法中,在一个组件内可以同时定义模板、数据、逻辑和样式。这样虽然可以使组件最大限度地独立,但是组件内的逻辑的复用非常麻烦。使用 Pinia 可以轻松实现跨组件的状态共享。

Pinia 是 Vue.js 3 官方推荐的状态管理库。集成 Pinia 只需要完成如下两步。

(1)安装 Pinia。在终端执行以下命令:

sh
$ yarn add pinia

(2)全局配置。在入口文件 main.ts 中加载 Pinia 模块,配置如下:

js
import { createPinia } from "pinia";
const app = createApp();
app.use(createPinia());

全局配置生效后,就可以使用 Pinia 创建 Store 并在组件中使用。之后会为首页和登录页分别创建一个 Store 存储各自页面用到的状态。

5.2.5 编写公共组件和公共函数

项目中的公共资源是在所有页面中都可以使用的通用资源。公共资源包括公共组件、公共函数和公共样式等。公共资源的封装是为了提高页面通用内容的可复用性,降低代码冗余,以及简化更新步骤。接下来编写一部分基础的公共资源。

公共头部组件

头部组件会在除登录页外的所有页面中展示,展示的内容包括已登录用户的信息和标题等。公共组件的名称统一以“Cus”开头,并且保存在 components 目录下,因此头部组件可命名为 CusHeader。

创建 components/CusHeader.vue 文件,用来表示公共头部组件。公共头部组件的内容比较简单,具体实现请参考本书的配套代码。

公共工具函数

公共函数统一定义在 utils/index.ts 文件中。在定义函数之后必须通过 export 关键字导出,以保证在组件中可以导入函数使用。

(1)编写一个时间处理函数,将时间处理为特定格式的字符串在页面中展示。时间处理需要借助第三方包 dayjs 实现。

安装 dayjs 包的代码如下:

sh
$ yarn add dayjs

编写 FormatTime()函数,接收时间参数并处理格式,返回最终格式,代码如下:

js
import datjs from "dayjs";
export const FormatTime = (date: Date | string) => {
  return datjs(date).format("YYYY/MM/DD hh:mm");
};

当页面组件中需要展示时间时,应使用 FormatTime()函数转换时间格式:

js
import { FormatTime } from "@/utils";
var time = FormatTime(new Date());

(2)分别编写从 localStorage 中获取和设置数据的函数,在函数内自动处理序列化/反序列化,方便在组件中与 localStorage 交互:

js
// 获取 localStorage
export const localGetItem = (key: string): any => {
  let data_str = localStorage.getItem(key);
  if (data_str) {
    return JSON.parse(data_str);
  }
  return null;
};
// 设置 localStorage
export const localSetItem = (key: string, value: any): void => {
  localStorage.setItem(key, JSON.stringify(value));
};

(3)编写一个生成随机数的函数,以便在创建备忘录和文件夹数据时生成唯一的 ID:

js
// 生成随机 ID
export const geneId = (): number => {
  return Math.floor(Math.random() * 939874);
};