工程化配置

还是开发体验的问题,跟开发体验有关的项目配置无非就是使用 eslint、prettier、stylelint 统一代码风格。

formatting and lint

eslint、prettier、stylelint 怎么配这里就不说了,网上文章太多了。想说的是eslint rule 'prettier/prettier': 'error'一定要开启,以及 stylelint rule 'prettier/prettier': true 也一定要开启。

虽然配置了eslint、prettier、stylelint,但是可能你队友的编辑器并没有装相应的插件,格式化用的也不是 prettier,然后他修改一行代码顺便把整个文件格式化了一遍。所以还得配置 husky + lint-staged,提交代码的时候按规范格式化回去,不符合规范的代码不允许提交。

如果公司的电脑配置还行的话,可以开发阶段就做相应的 lint, 把错误抛出来,中断编译。webpack 可以使用 eslint-loader,stylelint-webpack-plugin;vite 可以使用 vite-plugin-eslint,vite-plugin-stylelint;vue-cli 配置几个参数就可以开启,具体看文档。

ts-check

什么是 ts-check?举个例子,有一个后端接口的某个字段名称变了,由 user_name 改为了 userName,如果没有配置开发阶段进行 ts-check 并把错误抛出来,那么只能全局查找调用接口的地方去修改,如果改漏了,那就喜提一个 BUG。

ts-check 可以开发阶段就做,也可以提交代码的时候做。开发阶段 webpack 安装 fork-ts-checker-webpack-plugin ,vite 也是找相应的插件(暂时没找到用的比较多的)。提交代码的时候,结合 husky 做一次全量的 check (比较耗时),react 项目执行 tsc --noEmit --skipLibCheck,vue 项目执行 vue-tsc --noEmit --skipLibCheck

ts-check 能好用的前提是你的项目是 TS 写的,接口返回值有具体的类型定义,而不是 any。

代码规范

主要讲讲 model,service,presenter,view 这几层的代码规范,之前的文章也有简单提到过,这里做个归纳。

model

import { reactive, ref } from "vue";
import { IFetchUserListResult } from "./api"; export const useModel = () => {
const userList = reactive<{ value: IFetchUserListResult["result"]["rows"] }>({
value: [],
}); return {
userList,
};
}; export type Model = ReturnType<typeof useModel>;
  1. 每一个字段都要声明类型,不要因为字段多就用 Object[k: string]: string | number | booleanRecord<string, string> 之类的来偷懒。
  2. 可以包含一些简单逻辑的方法,比如重置 state。
  3. vue 中字段声明可以移到 useModel 外面,达到状态共享的作用,在 useModel 中 return 出去使用。

service

  1. react 技术栈,presenter 层调用的时候使用单例方法,避免每次re-render 都生成新的实例。
  2. service 要尽量保持“整洁”,不要直接调用特定环境,端的 API,尽量遵循 依赖倒置原则。比如 fetch,WebSocket,cookie,localStorage 等 web 端原生 API 以及 APP 端 JSbridge,不建议直接调用,而是抽象,封装成单独的库或者工具函数,保证是可替换,容易 mock 的。Taro,uni-app 等框架的 API 也不要直接调用,可以放到 presenter 层。组件库提供的命令式调用的组件,也不要使用。
  3. service 方法的入参要合理,不要为了适配组件库而声明不合理的参数,比如某个组件返回 string[] 类型的数据,实际只需要数组第一个元素,参数声明为 string 类型即可。2个以上参数改为使用对象。
  4. 业务不复杂可以省略 service 层。

service 保证足够的“整洁”,model 和 service 是可以直接进行单元测试的,不需要去关心是 web 环境还是小程序环境。

import { Model } from './model';

export default class Service {
private static _indstance: Service | null = null; private model: Model; static single(model: Model) {
if (!Service._indstance) {
Service._indstance = new Service(model);
}
return Service._indstance;
} constructor(model: Model) {
this.model = model;
}
}

presenter

import { message, Modal } from 'antd';
import { useModel } from './model';
import Service from './service'; const usePresenter = () => {
const model = useModel();
const service = Service.single(model); const handlePageChange = (page: number, pageSize: number) => {
service.changePage(page, pageSize);
}; return {
model,
handlePageChange,
};
}; export default usePresenter;
  1. 处理 view 事件的方法以 handle 或 on 开头。
  2. 不要出现过多的逻辑。
  3. 生成 jsx 片段的方法以 render 开头,比如 renderXXX。
  4. 不管是 react 还是 vue 不要解构 model,直接 model.xxxx 的方式使用。

view

  1. 组件 props 写完整类型。
  2. jsx 不要出现嵌套的三元运算。
  3. 尽量所有的逻辑都放到 presenter 中。
  4. 不要解构 presenter 以及 model,以 presenter.xxx,model.xxxx 方式调用。

store

  1. 不要在外层去使用内层的 store。

接口请求方法

  1. 封装的接口请求方法支持泛型
import axios, { AxiosRequestConfig } from "axios";
import { message } from "ant-design-vue"; const instance = axios.create({
timeout: 30 * 1000,
}); // 请求拦截
instance.interceptors.request.use(
(config) => {
return config;
},
(error) => {
return Promise.reject(error);
},
); // 响应拦截
instance.interceptors.response.use(
(res) => {
return Promise.resolve(res.data);
},
(error) => {
message.error(error.message || "网络异常");
return Promise.reject(error);
},
); type Request = <T = unknown>(config: AxiosRequestConfig) => Promise<T>; export const request = instance.request as Request;
  1. 具体接口的请求方法,入参及返回值都要声明类型,参数量最多两个,body 数据命名为 data,非 body 数据命名为 params,都是对象类型。
  2. 参数类型及返回值类型都声明放在一起,不需要用单独的文件夹去放,觉得代码太多不好看可以用 region 注释块折叠起来(vscode 支持)。
  3. 接口请求方法以 fetch,del,submit,post 等单词开头。
  4. 建议接口请求方法直接放在组件同级目录里,建一个 api.ts 的文件。很多人都习惯把接口请求统一放到一个 servcies 的文件夹里,但是复用的接口又有几个呢,维护代码的时候在编辑器上跨一大段距离来回切换文件夹真的是很糟糕的开发体验。
// #region 编辑用户
export interface IEditUserResult {
code: number;
msg: string;
result: boolean;
} export interface IEditUserParams {
id: number;
} export interface IEditUserData {
name: string;
age: number;
mobile: string;
address?: string;
tags?: string[];
} /**
* 编辑用户
* http://yapi.smart-xwork.cn/project/129987/interface/api/1796964
* @author 划水摸鱼糊屎工程师
*
* @param {IEditUserParams} params
* @param {IEditUserData} data
* @returns
*/
export function editUser(params: IEditUserParams, data: IEditUserData) {
return request<IEditUserResult>(`${env.API_HOST}/api/user/edit`, {
method: 'POST',
data,
params,
});
} // #endregion

上面代码是工具生成的,下篇说说提升开发效率及体验的工具。

如何结合整洁架构和MVP模式提升前端开发体验(三) - 项目工程化配置、规范篇的更多相关文章

  1. 如何结合整洁架构和MVP模式提升前端开发体验(二) - 代码实现篇

    上一篇文章介绍了整体架构,接下来说说怎么按照上图的分层结构实现下面的增删改查的功能. 代码结构 vue userManage └── List ├── api.ts ├── EditModal │ ├ ...

  2. 如何结合整洁架构和MVP模式提升前端开发体验 - 整体架构篇

    本文不详细介绍什么是整洁架构以及 MVP 模式,自行查看文章结尾相关链接文章. 整洁架构粗略介绍 下图为整洁架构最原始的结构图: Entities/Models:实体层,官方说法就是封装了企业里最通用 ...

  3. MVP模式在Android开发中的应用

    一.MVP介绍      随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互.同一 ...

  4. 基于ASP.NET WPF技术及MVP模式实战太平人寿客户管理项目开发(Repository模式)

    亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的.能够加我的QQ2059055336和我联系.  课程背景 本课程是教授使用WPF.ADO.NET.MVVM技术来实现太平人寿保险有限公司 ...

  5. [译]Google官方关于Android架构中MVP模式的示例

    概述 该示例(TODO-MVP)是后续各种示例演变的基础,它主要演示了在不带架构性框架的情况下实现M-V-P模式.其采用手动依赖注入的方式来提供本地数据源和远程数据源仓库.异步任务通过回调处理. 注意 ...

  6. Google官方关于Android架构中MVP模式的示例续-DataBinding

    基于前面的TODO示例,使用Data Binding库来显示数据并绑定UI元素的响应动作. 这个示例并未严格遵循 Model-View-ViewModel 或 Model-View-Presenter ...

  7. 通过Swagger文档生成前端service文件,提升前端开发效率

    在企业级的项目开发过程中,一般会采用前后端分离的开发方式,前后端通过api接口进行通信,所以接口文档就显得十分的重要. 目前大多数的公司都会引入Swagger来自动生成文档,大大提高了前后端分离开发的 ...

  8. .Net平台-MVP模式初探(一)

    为什么要写这篇文章 笔者当前正在负责研究所中一个项目,这个项目基于.NET平台,初步拟采用C/S部署体系,所以选择了Windows Forms作为其UI.经过几此迭代,我们发现了一个问题:虽然业务逻辑 ...

  9. 说说Android的MVP模式

    http://toughcoder.NET/blog/2015/11/29/understanding-Android-mvp-pattern/ 安卓应用开发是一个看似容易,实则很难的一门苦活儿.上手 ...

随机推荐

  1. cve-2021-42287和cve-2021-42278漏洞复现

    一.漏洞概述 cve-2021-42287 : 由于Active Directory没有对域中计算机与服务器账号进行验证,经过身份验证的攻击 者利用该漏洞绕过完全限制,可将域中普通用户权限提升为域管理 ...

  2. VS Code 调教日记(2022.6.26更新)

    VS Code 调教日记(2022.6.26更新) 基于msys2的MinGW-w64 GCC的环境配置 下载并安装msys2 到路径...msys2安装路径...\msys64\etc\pacman ...

  3. 广西省行政村边界shp数据/广西省乡镇边界/广西省土地利用分类数据/广西省气象数据/降雨量分布数据/太阳辐射数据

    ​  数据下载链接:数据下载链接 广西壮族自治区,地处中国南部,北回归线横贯中部,属亚热带季风气候区.南北以贺州--东兰一线为界,此界以北属中亚热带季风气候区,以南属南亚热带季风气候区. 数据范围:全 ...

  4. 如何在.Net Framework应用中请求HTTP2站点

    背景介绍 本文的需求背景是对接苹果公司的推送服务(APNS),苹果在安全方面比较积极,已经严格限制API只支持HTTP2.但是我这里的应用目前仍然是.NET Framework平台,所以必须寻找一种解 ...

  5. 数据结构-查找-二叉排序查找(平衡二叉树,B树,B+树概念)

    0.为什么需要二叉排序树 1)数组存储方式: 优点:通过下标访问元素,速度快,对于有序数组,可以通过二分查找提高检索效率: 缺点:如果检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低: 2 ...

  6. Collection集合概述和集合框架介绍avi

    集合概述 在前面基础班我们已经学习过并使用过集合ArrayList<E> ,那么集合到底是什么呢?· ~集合︰集合是java中提供的一种容器,可以用来存储多个数据集合和数组既然都是容器,它 ...

  7. Css3入门详解

    一.Css基本语法 1.Html和Css没分开时 点击查看代码 <!DOCTYPE html> <html lang="en"> <head> ...

  8. git无法使用Tab提示

    1.过去git版本: git version 2.获取git-completion.bash脚本,注意将下方链接的版本号改为和git版本一致. https://raw.githubuserconten ...

  9. Josephus问题(Ⅰ)

    题目描述 n个人排成一圈,按顺时针方向依次编号1,2,3-n.从编号为1的人开始顺时针"一二"报数,报到2的人退出圈子.这样不断循环下去,圈子里的人将不断减少.最终一定会剩下一个人 ...

  10. java发送http请求get/post

    1,导入依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId> ...