Angularjs 产品重构二

发布时间 2023-04-28 16:12:57作者: 艾前端

Angularjs 产品重构二

接上一篇 《 Angularjs 产品重构一》 介绍了重构背景、立项、准备工作和技术选型,本篇文章介绍重构的具体事宜。

重构

技术选项完成后,就进入重构阶段了,vue3 选择的是组合式 API,结合 setup 语法,和写原生的 ES 很像了。

1. 结构

结构目录

根目录下配置文件说明:

1.1. .browserslistrc 文件

参考:browserslist

目的:配置兼容浏览器

  • > 1% 代表着全球超过 1%人使用的浏览器
  • last 2 versions 表示所有浏览器兼容到最后两个版本
  • not dead

dead 的定义:

browsers without official support or updates for 24 months. Right now it is IE 11, IE_Mob 11, BlackBerry 10, BlackBerry 7, Samsung 4, OperaMobile 12.1 and all versions of Baidu.

不包括 IE11,因为 browserslist 项目在 2022 年 06 月 21 日提交了: Mark Internet Explorer as dead (#701) 链接,将 Internet Explorer 标记为已死。

1.2. .env.development 文件

开发环境下的配置文件。

1.3. .env.production 文件

生产环境下的配置文件。

1.4. .eslintignore 文件

ESLint 就是我们在开发过程中用来检测 ES 代码的规范的一个工具。在该文件中可以指定哪些文件和文件夹里面的文件不被 ESLint 检查。

1.5. .eslintrc.js 文件

参考:eslint

配置 ESLint 规则。ESLint 支持几种格式的配置文件:

  • JavaScript - 使用 .eslintrc.js 然后输出一个配置对象。
  • YAML - 使用 .eslintrc.yaml 或 .eslintrc.yml 去定义配置的结构。
  • JSON - 使用 .eslintrc.json 去定义配置的结构,ESLint 的 JSON 文件允许 JavaScript 风格的注释。
  • (弃用) - 使用 .eslintrc,可以使 JSON 也可以是 YAML。
  • package.json - 在 package.json 里创建一个 eslintConfig 属性,在那里定义你的配置。

如果同一个目录下有多个配置文件,ESLint 只会使用一个。优先级顺序如下:

  1. .eslintrc.js
  2. .eslintrc.yaml
  3. .eslintrc.yml
  4. .eslintrc.json
  5. .eslintrc
  6. package.json

1.6. gitattributes 文件

.gitattributes 文件中可以定义的属性

  • text 用于控制行尾的规范性。如果一个文本文件是规范的,则 Git 库汇总该文件(git 服务器上的文件)的行尾总是 LF。对于工作目录,除了 text 属性之外,还可以设置 eol 属性或 core.eol 配置变量。

  • eol

设置行末字符。

eol=lf ,[回车] :入库时将行尾规范为 LF,检出时行尾不强制转换为 CRLF eol=crlf,[换行、回车] :入库时将行尾规范为 LF,检出时将行尾转换为 CRLF

github 可以对整个项目进行语言统计。

*.ts linguist-detectable=false 代表弃用 ts 语言统计 *.vue linguist-detectable=true 代表弃用 vue 文件统计

1.7. .gitignore 文件

git 忽略文件。

在工程中,并不是所有文件都需要保存到版本库中的,例如 node_modules 目录及目录下的文件就可以忽略。

1.8. .prettierignore 文件

Prettier 忽略指定文件。

1.9. .stylelintignore 文件

stylelint 忽略文件。

1.10. yarnrc 文件

.yarnrc 文件允许你配置额外的 Yarn 特性。config 命令也可以用来设置这些选项。Yarn 将.yarnrc 文件合并到文件树中。

1.11. commitlint.config.js 文件

代码提交规范。

描述
feat 新增一个功能
fix 修复一个 bug
docs 文档变更
style 代码格式(不影响功能,例如空格、分号等格式修正)
refactor 代码重构
perf 改善性能
test 测试
build 变更项目构建或外部依赖
ci 更改持续集成软件的配置文件和 package.json 中的 scripts 命令,例如: scopes: Travis, Circle 等
chore 变更构建流程或辅助工具
revert 代码回退

1.12. LICENSE 文件

许可证,例如 麻省理工学院的许可

1.13. package.json 文件

npm 包管理配置文件,将项目通过 npm 管理时(npm init -y),将生成此文件。可在里面配置说明项目的名称(name)、版本(version)、依赖(dependencies、devDependencies)、脚本命令(scripts)和其他(如许可 license,引擎 engines 等)。

1.14. postcss.config.js 文件

postcss-px-to-viewport

postcss-px-to-viewport 是一款 PostCSS 插件,用于将 px 单位转化为 vw/vh 单位。

1.15. prettier.config.js 文件

prettier (代码格式工具)配置文件。

prettier 不会像 EsLint, StyleLint 那样告诉你语法哪里错了,它只会告诉你代码这么写不美观。

Configuration File

1.16. README.md 文件

本项目说明文件。

1.17. stylelint.config.js 文件

rules

.declaration-order {
  /* 1.Positioning 位置属性 */ 
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10;
 
  /* 2.Box Model 盒子属性 */
  display: block;
  float: right;
  width: 100px;
  height: 100px;
  margin: 10px;
  padding: 10px;
 
  /* 3.Typography 文字属性 */
  color: #888;
  font: normal 16px Helvetica, sans-serif;
  line-height: 1.3;
  text-align: center;
 
  /* 4.Visual 视觉属性 */
  background-color: #eee;
  border: 1px solid #888;
  border-radius: 4px;
  opacity: 1;
 
  /* 5.Animation Misc 其他 */
  transition: all 1s;
  user-select: none;
}

1.18. tsconfig.json 文件

tsconfig.json 含义

如果一个目录下存在一个 tsconfig.json 文件,那么它意味着这个目录是 TypeScript 项目的根目录。该文件中指定了用来编译这个项目的根文件和编译选项。

{
  "compilerOptions": {
    "target": "esnext", // 指定ECMAScript目标版本 "ES3"(默认), "ES5", "ES6"/ "ES2015", "ES2016", "ES2017"或 "ESNext"。注意: "ESNext"最新的生成目标列表为 ES proposed features
    "module": "esnext", // 指定生成哪个模块系统代码
    "moduleResolution": "node", // 决定如何处理模块。或者是"Node"对于Node.js/io.js,或者是"Classic"(默认)。
    "strict": true, // 启用所有严格类型检查选项。
    "noLib": false, // 不包含默认的库文件( lib.d.ts)
    "forceConsistentCasingInFileNames": true, // 禁止对同一个文件的不一致的引用
    "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
    "strictFunctionTypes": false, // 禁用函数参数双向协变检查。
    "jsx": "preserve", // 在 .tsx文件里支持 JSX: "React" 或 "Preserve"
    "baseUrl": ".", // 解析非相对模块名的基准目录
    "allowJs": true, // 允许编译javascript文件
    "sourceMap": true, // 生成相应的 .map 文件
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "noUnusedLocals": true, // 若有未使用的局部变量则抛错
    "noUnusedParameters": true,  // 若有未使用的参数则抛错
    "experimentalDecorators": true, // 启用实验性的ES装饰器
    "lib": ["dom", "esnext"], // 编译过程中需要引入的库文件的列表
    "noImplicitAny": false, // 在表达式和声明上有隐含的 any 类型时报错
    "skipLibCheck": true, // 忽略所有的声明文件( *.d.ts)的类型检查。
    "types": ["node", "vite/client", "unplugin-vue-define-options"], // 要包含的类型声明文件名列表
    "removeComments": true, // 删除所有注释,除了以 /!*开头的版权信息。
    "paths": {
      "@/*": ["src/*"]
    }
  },
}

1.19. yarn.lock 文件

Yarn 利用项目根目录下的 yarn.lock 文件来确保依赖解析时又快又稳定。yarn 会报关这个文件并在管理依赖项时修改这个文件。

为了保证你应用的行为保持一致,应该把 yarn.lock 文件提交到代码仓库中。

2. src 目录下结构说明

2.1. assets

存放静态资源,如 icons,images, videos

2.2. components

存放公共组件。

2.3. constants

存放常量文件,每一个模块都会包含一些常量,例如一些 Map:

const MSexMap = new Map([
  [1, '男性'],
  [2, '女性'],
]);

export { MSexMap };

2.4. cores

核心文件,例如 i18n,用来配置国际化语言。

2.5. data

一些本地数据,例如统计局发布的地区数据,可以存储在本地,减少向服务端发起请求。

2.6. layouts

培训布局页面,包裹所有业务代码页面,便于在此页面中导入公共组件,便于公用。

2.7. models

一些公共的 model,导出 interface。

2.8. modeuls

一些公共模块,是一个完整的功能,其中可能包含 component、service、model、view,拷贝到其它项目中就能使用的模块,不需要关心里面具体包含的东西。

2.9. plugins

引入的外部插件,例如富文本插件,vant 插件。

2.10. routers

项目的路由配置。

2.11. services

项目配置的接口文档。

2.12. stores

pinia 存储等。

2.13. styles

公共的样式表,例如一些重置样式,reset.scss。

2.14. utils

一些工具函数。

2.15. views

项目中涉及的视图页面。

3. 开发流程

因为 TS 控制着严控的格式,为了在编写业务代码时使用点语法就能轻松获取属性,需要在开发业务前做一些准备工作。

3.1. 编写 model

定义 models 文件夹,其中包含 index.ts 文件,导出 userModel.ts

// models/index.ts
export * from './userModel';
// models/userModel.ts
/**
 * @description 获取用户列表 /user/list
 */
export interface IGetUserListRequests {
  page: number; // 页码
  pageSize: number; // 每页条数
}

export interface IGetUserListResponses {
  list: IGetUserListData[];
  page: number; // 页码
  pageSize: number; // 每页条数
  total: number; // 总数
}

export interface IGetUserListData {
  userId: number; // 用户ID
  userName: string; // 用户姓名
  age: number; // 年龄
  sex: number; // 性别
}

3.2. 编写对应 Map

如上获取用户列表接口返回的字段中,包含性别,性别使用 number,为了在视图中显示“男”或“女”,需要编写 Map 对应

// contants/userMap.ts
const MSexMap = new Map([
  [1, '男性'],
  [2, '女性']
]);

export { MSexMap };

3.3. 编写 Sevice

定义 services 文件夹,其中包含 index.ts 文件,导出 userService.ts

定义了接口的请求参数和返回参数后,可以编写接口了。

// userService.ts
import { IGetUserListRequests, IGetUserListResponses } from './models';
import request from '@/utils/http';

enum API {
  getUserList = '/users', // 获取用户列表
}

export const getUserList = (data: IGetUserListRequests) => {
  return request<IGetUserListResponses>({
    url: API.getUserList,
    method: 'get',
    hideLoading: true,
    data,
  });
};

/utils/http 文件做了一次 axios 封装,可以拦截请求和返回。例如拦截请求,统一给 http 请求加上请求头,拦截 http 响应时,判断登录是否已过期,过期后跳转到登录页面。

3.4. 编写业务代码,请求接口

在业务代码 vue 单组件文件中,先导入接口,然后就可以使用了。

import { Ref, ref, onMounted } from 'vue';
import { getUserList } from '@/services';

const users: Ref<IGetUserListData> = ref([]);
const loading = ref(true);

onMounted(() => {
  getUserListFn();
});
// 获取用户信息
function getUserListFn(): void {
  getUserList()
    .then((res) => {
      loading.value = false;
      const data = res?.data;
      users.value = data.list;
    })
    .catch(() => {
      loading.value = false;
    });
}

到此,就介绍完了一个页面开发的全部流程。model / contants / data ---> service ---> view。