From 4d634887ba48e3ad3f7c81d293b7c25c3206cae3 Mon Sep 17 00:00:00 2001 From: zhuoda Date: Fri, 9 Dec 2022 18:48:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=A3=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 代码规范/Java规范 V2.0.md | 612 +++++++++++++++++++++++++++++++++ 代码规范/Vue3规范 V2.0.md | 704 ++++++++++++++++++++++++++++++++++++++ 代码规范/规范导读 V2.0.md | 219 ++++++++++++ 3 files changed, 1535 insertions(+) create mode 100644 代码规范/Java规范 V2.0.md create mode 100644 代码规范/Vue3规范 V2.0.md create mode 100644 代码规范/规范导读 V2.0.md diff --git a/代码规范/Java规范 V2.0.md b/代码规范/Java规范 V2.0.md new file mode 100644 index 00000000..4301eded --- /dev/null +++ b/代码规范/Java规范 V2.0.md @@ -0,0 +1,612 @@ +--- +title: 2.3、Java规范 V2.0 +date: 2022-09-07 +--- +## 阅读须知 + +**在阅读《Java规范》之前,请一定先阅读上一篇《规范导读 V2.0》!!!** ,[前往阅读](./basic.md) + +## 一、Java 项目规范 + +### 1.1、Java 项目命名规范 + +全部采用小写方式, 以中划线分隔。 + +```java +正例:`mall-management-system / order-service-client / user-api` + +反例:`mall_management-system / mallManagementSystem / orderServiceClient` +``` + +### 1.2、方法参数规范 + +无论是 `controller,service,manager,dao` 亦或是**其他 class 的**代码,每个方法最多 `5` 个参数,如果超出 `5` 个参数的话,要封装成 `javabean` 对象。 + +- 方便他人调用,降低出错几率。尤其是当参数是同一种类型,仅仅依靠顺序区分,稍有不慎便是灾难性后果,而且排查起来也极其恶心。 +- 保持代码整洁、清晰度。当一个个方法里充斥着一堆堆参数的时候,再坚强的人,也会身心疲惫。 + +反例: + +```java +/** +* 使用证书加密数据工具方法 +* +* @param param 参数 +* @param password 加密密码 +* @param priCert 私钥 +* @param pubCert 公钥 +* @param username 用户名 +* @param ip ip地址 +* @param userAgent 用户特征 +* @return 返回加密后的字符串 +*/ +public String signEnvelop(JdRequestParam param, String password, String priCert, String pubCert, String username, String ip, String userAgent){ + +} +``` + +### 1.3、代码目录结构 + +统一的目录结构是所有项目的基础。 + +```xml +src 源码目录 +|-- common 各个项目的通用类库 +|-- config 项目的配置信息 +|-- constant 全局公共常量 +|-- handler 全局处理器 +|-- interceptor 全局连接器 +|-- listener 全局监听器 +|-- module 各个业务(方便将来拆成微服务) +|-- |--- employee 员工模块 +|-- |--- role 角色模块 +|-- |--- login 登录模块 +|-- third 三方服务,比如redis, oss,微信sdk等等 +|-- util 全局工具类 +|-- Application.java 启动类 +``` + +### 1.4、common 目录规范 + +common 目录用于存放各个项目通用的项目,但是又可以依照项目进行特定的修改。 + +```java +src 源码目录 +|-- common 各个项目的通用类库 +|-- |--- anno 通用注解,比如权限,登录等等 +|-- |--- constant 通用常量,比如 ResponseCodeConst +|-- |--- domain 全局的 javabean,比如 BaseEntity,PageParamDTO 等 +|-- |--- exception 全局异常,如 BusinessException +|-- |--- json json 类库,如 LongJsonDeserializer,LongJsonSerializer +|-- |--- swagger swagger 文档 +|-- |--- validator 适合各个项目的通用 validator,如 CheckEnum,CheckBigDecimal 等 +``` + +### 1.5、module 目录规范 + +module 目录里写项目的各个业务,每个业务一个独立的顶级文件夹,在文件里进行 mvc 的相关划分。 +其中,domain 包里存放 entity, dto, vo,bo 等 javabean 对象 + +```java +src +|-- module 所有业务模块 +|-- |-- role 角色模块 +|-- |-- |--RoleController.java controller +|-- |-- |--RoleConst.java role相关的常量 +|-- |-- |--RoleService.java service +|-- |-- |--RoleDao.java dao +|-- |-- |--domain domain +|-- |-- |-- |-- RoleEntity.java 表对应实体 +|-- |-- |-- |-- RoleForm.java 请求Form对象 +|-- |-- |-- |-- RoleVO.java 返回对象 +|-- |-- employee 员工模块 +|-- |-- login 登录模块 +|-- |-- email 邮件模块 +|-- |-- .... 其他 +``` + +## 二、MVC 规范 + +### 2.1、整体分层 + +- controller 层 +- service 层 +- manager 层 +- dao 层 + +### 2.2、 `controller` 层规范 + +#### 1) 只允许在 method 上添加 `RequestMapping` 注解 + +只允许在 method 上添加 `RequestMapping` 注解,不允许加在 `class` 上(为了方便的查找 url,放到 class 上 url 不能一次性查找出来) + +正例: + +```java +@RestController +public class DepartmentController { + + @GetMapping("/department/list") + public ResponseDTO> listDepartment() { + return departmentService.listDepartment(); + } +``` + +反例: + +```java +@RequestMapping ("/department") +public class DepartmentController { + + @GetMapping("/list") + public ResponseDTO> listDepartment() { + return departmentService.listDepartment(); + } +``` + +#### 2)不推荐使用 restful 命名 url + +不推荐使用 restful 命名 url, 只能使用 `get/post` 方法。url 命名遵循:**`/业务模块/子模块/动作`** ; +其中 `业务模块和子模块` 使用 名字, `动作` 使用动词; +原因: + +> **虽然 restful 大法好,但是有时并不能一眼根据 url 看出来是什么操作,所以我们选择了后者,这个没有对与错,只有哪个更适合我们的团队** + +正例: + +```java +GET /department/get/{id} 查询某个部门详细信息 +POST /department/query 复杂查询 +POST /department/add 添加部门 +POST /department/update 更新部门 +GET /department/delete/{id} 删除部门 + +GET /department/employee/delete/{id} 删除部门员工 +``` + +#### 3)swagger 接口注释必须加上后端作者 + +每个方法必须添加 `swagger` 文档注解 `@ApiOperation` ,并填写接口描述信息,描述最后必须加上接口的作者信息,格式如下: `@author 卓大` + +正例: + +```java + @ApiOperation("更新部门信息 @author 卓大") + @PostMapping("/department/update") + public ResponseDTO updateDepartment(@Valid @RequestBody DepartmentUpdateForm departmentUpdateForm) { + return departmentService.updateDepartment(departmentUpdateForm); + } + +``` + +#### 4)controller 每个方法要保持简洁 + +controller 在mvc中负责协同和委派业务,充当路由的角色,所以要保持代码少量和清晰,要做到如下要求: + +- 不做任何的业务逻辑操作 +- 不做任何的参数、业务校验,参数校验只允许使用@Valid 注解做简单的校验 +- 不做任何的数据组合、拼装、赋值等操作 + +正例: + +```java + @ApiOperation("添加部门 @author 卓大") + @PostMapping("/department/add") + public ResponseDTO addDepartment(@Valid @RequestBody DepartmentAddForm departmentAddForm) { + return departmentService.addDepartment(departmentAddForm); + } +``` + +#### 5)只能在 `controller` 层获取当前请求用户 + +只能在 `controller` 层获取当前请求用户,并传递给 `service` 层。 +> **因为获取当前请求用户是从 ThreadLocal 里获取取的,在 service、manager、dao 层极有可能是其他非 request 线程调用,会出现 null 的情况,尽量避免** + +```java + @ApiOperation("添加员工 @author 卓大") + @PostMapping("/employee/add") + public ResponseDTO addEmployee(@Valid @RequestBody EmployeeAddForm employeeAddForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + return employeeService.addEmployee(employeeAddForm, requestUser); + } +``` + +### 2.3、 `service` 层规范 + +#### 1) 合理拆分 service 业务 + +我们不建议service文件行数太大 ,如果业务较大,请拆分为多个 service; + +如订单业务,所有业务都写到 OrderService 中会导致文件过大,故需要进行拆分如下: + +- `OrderQueryService` 订单查询业务 +- `OrderCreateService` 订单新建业务 +- `OrderDeliverService` 订单发货业务 +- `OrderValidatorService` 订单验证业务 + +#### 2) 谨慎使用 `@Transactional` 事务注解 + +谨慎使用 `@Transactional` 事务注解的使用,不要简单对 `service` 的方法添加个 `@Transactional` 注解就觉得万事大吉了。 +应当合并对数据库的操作,尽量减少添加了`@Transactional`方法内的业务逻辑。 +`@Transactional` 注解内的 `rollbackFor` 值必须使用异常 `Exception.class` + +> _对于@Transactional 注解,当 spring 遇到该注解时,会自动从数据库连接池中获取 connection,并开启事务然后绑定到 ThreadLocal 上,如果业务并没有进入到最终的 操作数据库环节,那么就没有必要获取连接并开启事务,应该直接将 connection 返回给数据库连接池,供其他使用(比较难以讲解清楚,如果不懂的话就主动去问)。_ + +反例: + +```java + @Transactional(rollbackFor = Exception.class) + public ResponseDTO upOrDown(Long departmentId, Long swapId) { + // 验证 1 + DepartmentEntity departmentEntity = departmentDao.selectById(departmentId); + if (departmentEntity == null) { + return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS); + } + // 验证 2 + DepartmentEntity swapEntity = departmentDao.selectById(swapId); + if (swapEntity == null) { + return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS); + } + // 验证 3 + Long count = employeeDao.countByDepartmentId(departmentId) + if (count != null && count > 0) { + return ResponseDTO.wrap(DepartmentResponseCodeConst.EXIST_EMPLOYEE); + } + // 操作数据库 4 + Long departmentSort = departmentEntity.getSort(); + departmentEntity.setSort(swapEntity.getSort()); + departmentDao.updateById(departmentEntity); + swapEntity.setSort(departmentSort); + departmentDao.updateById(swapEntity); + return ResponseDTO.succ(); + } +``` + +以上代码前三步都是使用 connection 进行验证操作,由于方法上有@Transactional 注解,所以这三个验证都是使用的同一个 connection。 + +若对于复杂业务、复杂的验证逻辑,会导致整个验证过程始终占用该 connection 连接,占用时间可能会很长,直至方法结束,connection 才会交还给数据库连接池。 + +对于复杂业务的不可预计的情况,长时间占用同一个 connection 连接不是好的事情,应该尽量缩短占用时间。 + +正例: + +```java + DepartmentService.java + + public ResponseDTO upOrDown(Long departmentId, Long swapId) { + DepartmentEntity departmentEntity = departmentDao.selectById(departmentId); + if (departmentEntity == null) { + return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS); + } + DepartmentEntity swapEntity = departmentDao.selectById(swapId); + if (swapEntity == null) { + return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS); + } + Long count = employeeDao.countByDepartmentId(departmentId) + if (count != null && count > 0) { + return ResponseDTO.wrap(DepartmentResponseCodeConst.EXIST_EMPLOYEE); + } + departmentManager.upOrDown(departmentSort,swapEntity); + return ResponseDTO.succ(); + } + + + DepartmentManager.java + + @Transactional(rollbackFor = Throwable.class) + public void upOrDown(DepartmentEntity departmentEntity ,DepartmentEntity swapEntity){ + Long departmentSort = departmentEntity.getSort(); + departmentEntity.setSort(swapEntity.getSort()); + departmentDao.updateById(departmentEntity); + swapEntity.setSort(departmentSort); + departmentDao.updateById(swapEntity); + } + +``` + +将数据在 service 层准备好,然后传递给 manager 层,由 manager 层添加@Transactional 进行数据库操作。 + +**以上是使用`manager`去处理解决的,其实也可以是使用spring的 `TransactionTemplate ` 事务模板解决** + +#### 3)需要注意的是:注解 `@Transactional` 事务在类的内部方法调用是不会生效的 + +反例:如果发生异常,saveData 方法上的事务注解并不会起作用 + +```java +@Service +public class OrderService{ + + public void createOrder(OrderAddForm addForm){ + this.saveData(addForm); + } + + @Transactional(rollbackFor = Exception.class) + public void saveData(OrderAddForm addForm){ + orderDao.insert(addForm); + } +} +``` + +> _Spring 采用动态代理(AOP)实现对 bean 的管理和切片,它为我们的每个 class 生成一个代理对象。只有在代理对象之间进行调用时,可以触发切面逻辑。而在同一个 class 中,方法 A 调用方法 B,调用的是原对象的方法,而不通过代理对象。所以 Spring 无法拦截到这次调用,也就无法通过注解保证事务了。简单来说,在同一个类中的方法调用,不会被方法拦截器拦截到,因此事务不会起作用。_ + +解决方案: + +1. 可以将方法放入另一个类,如新增 `manager层`,通过 spring 注入,这样符合了在对象之间调用的条件。 +2. 启动类添加` @EnableAspectJAutoProxy(exposeProxy = true)`,方法内使用`AopContext.currentProxy()`获得代理类,使用事务。 + +```java +SpringBootApplication.java + +@EnableAspectJAutoProxy(exposeProxy = true) +@SpringBootApplication +public class SpringBootApplication {} + +OrderService.java + +public void createOrder(OrderCreateDTO createDTO){ + OrderService orderService = (OrderService)AopContext.currentProxy(); + orderService.saveData(createDTO); +} +``` + + +### 2.4、 manager 层规范 + +manager 层的作用(引自《阿里 java 手册》): + +- 对第三方平台封装的层,预处理返回结果及转化异常信息; +- 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理; +- 与 DAO 层交互,对多个 DAO 的组合复用。 + + +### 2.5、 dao 层规范 + +#### 1)持久层框架选择 +优先使用 mybatis-plus 框架。如果需要多个数据源操作的,可以选择使用 我们实验室的 [SmartDb](https://gitee.com/lab1024/smartdb.git) 框架。 + +#### 2)使用mybatis-plus的要求 + +- 所有 Dao 继承自 BaseMapper +- 禁止使用 Mybatis-plus 的 Wrapper 条件构建器 +- 禁止直接在 mybatis xml 中写死常量,应从 dao 中传入到 xml 中 + + +正例: +NoticeDao.java 常量在参数中传入到xml +```java +public interface NoticeDao{ + + Integer noticeCount(@Param("sendStatus") Integer sendStatus); + +} +``` +NoticeMapper.xml +```xml + +``` + +反例:常量直接写死到 xml 中 + +```java +public interface NoticeDao{ + + Integer noticeCount(); + +} +``` +NoticeMapper.xml +```xml + +``` + +#### 4)连接join写法 +建议在xml中的 join 关联写法使用表名的全称,而不是用别名,对于关联表太多的话,在xml格式中,其实很难记住 别名是什么意思! + +反例: t_notice 别名 tn,t_employee别名 e, 在xml中已经很难区分是什么意思了,索性不如使用全称 +```xml + +``` +正确:使用全称 +```xml + +``` + +### 2.6、 javabean 命名规范 + +1) `javabean` 的整体要求: +- 不得有任何的业务逻辑或者计算 +- 基本数据类型必须使用包装类型`(Integer, Double、Boolean 等)` +- 不允许有任何的默认值 +- 每个属性必须添加注释,并且必须使用多行注释。 +- 必须使用 `lombok` 简化 `getter/setter` 方法 +- 建议对象使用 `lombok` 的 `@Builder ,@NoArgsConstructor`,同时使用这两个注解,简化对象构造方法以及 set 方法。 + +2)javabean 名字划分: +- XxxEntity 数据库持久对象 +- XxxVO 返回前端对象 (一些大厂用 Resp结尾,比如 XxxxResp) +- XxxForm 前端请求对象 (一些大厂用 Req结尾,比如 XxxxReq) +- XxxDTO 数据传输对象 +- XxxBO 内部处理对象 + +3)数据对象;`XxxxEntity`,要求: + +- 以 `Entity` 为结尾(阿里是为 DO 为结尾) +- Xxxx 与数据库表名保持一致 +- 类中字段要与数据库字段保持一致,不能缺失或者多余 +- 类中的每个字段添加注释,并与数据库注释保持一致 +- 不允许有组合 +- 项目内的日期类型必须统一,使用 `java.time.LocalDateTime` 或者 `java.time.LocalDate` + +4)请求对象;`XxxxForm`,要求: + +- 不可以继承自 `Entity` +- `Form` 可以继承、组合其他 `DTO,VO,BO` 等对象 +- `Form` 只能用于前端、RPC 的请求参数 + +3)返回对象;`XxxxVO`,要求: + +- 不可继承自 `Entity` +- `VO` 可以继承、组合其他 `DTO,VO,BO` 等对象 +- `VO` 只能用于返回前端、rpc 的业务数据封装对象 + +4)业务对象 `BO`,要求: + +- 不可以继承自 `Entity` +- `BO` 对象只能用于 `service,manager,dao` 层,不得用于 `controller` 层 + +### 2.7、boolean 类型的属性命名规范 + +> 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC 在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。 + +这是阿里巴巴开发手册中的原文,我们团队的规定是:`boolean` 类型的类属性和数据表字段都统一使用 `flag` 结尾。虽然使用 `isDeleted,is_deleted` 从字面语义上更直观,但是比起可能出现的潜在错误,这点牺牲还是值得的。 + +正例: + +``` +deletedFlag,deleted_flag,onlineFlag,online_flag +``` + +## 三、数据库 规范 + +### 3.1、数据库命名 + +全部采用小写方式, 以下划线分隔,并且区分是什么环境的数据库 + +```sql +正例:smart_admin_v2_dev / smart_admin_v2_prod / smart_admin_v2_test + +反例:mall_management-system / mallManagementSystem / orderServiceClient +``` + +### 3.2、表命名 +全部采用小写方式, 以下划线分隔,并且并且以 `t_` 开头 + +比如:员工表:`t_employee`、部门表:`t_department`、配置表:`t_config` + +### 3.3、建表规范 + +表必备三字段:id, create_time, update_time + +- id 字段 Long 类型,单表自增,自增长度为 1 +- create_time 字段 datetime 类型,默认值 CURRENT_TIMESTAMP +- update_time 字段 datetime 类型,默认值 CURRENT_TIMESTAMP, On update CURRENT_TIMESTAMP + +**#### 枚举类表字段注释需要将所有枚举含义进行注释** + +修改或增加字段的状态描述,必须要及时同步更新注释。如下表的 `sync_status` 字段 `同步状态 0 未开始 1同步中 2同步成功 3失败`。 + +正例: +```sql +CREATE TABLE `t_change_data` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `sync_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '同步状态 0 未开始 1同步中 2同步成功 3失败', + `sync_time` DATETIME NULL DEFAULT NULL COMMENT '同步时间', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`change_data_id`) +) +``` + +反例: +```sql +CREATE TABLE `t_change_data` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `sync_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '同步状态 ', + `sync_time` DATETIME NULL DEFAULT NULL COMMENT '同步时间', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`change_data_id`) +) +``` + +### 3.4、索引规范 + +具体索引规范请参照《阿里巴巴 Java 开发手册》索引规约 + + +## 联系我们 + +[1024创新实验室-主任:卓大](https://zhuoda.vip),混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。 +[1024创新实验室(河南·洛阳)](https://1024lab.net) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目。 + + + + + + + + + + + +
加 主任 “卓大” 微信
拉你入群,一起学习
关注 “小镇程序员”
分享代码与生活、技术与赚钱
请 “1024创新实验室” 喝咖啡
支持我们的开源与分享
diff --git a/代码规范/Vue3规范 V2.0.md b/代码规范/Vue3规范 V2.0.md new file mode 100644 index 00000000..a8d3070d --- /dev/null +++ b/代码规范/Vue3规范 V2.0.md @@ -0,0 +1,704 @@ +--- +title: 2.2、Vue3规范 V2.0 +date: 2022-09-07 +--- +## 阅读须知 + +**在阅读《Java规范》之前,请一定先阅读上一篇《规范导读 V2.0》!!!** ,[前往阅读](./basic.md) + + +## 一、Vue3 基础规范 + +### 1.1、项目命名 + +全部采用小写方式, 以中划线分隔。 +```javascript +正例:`smart-admin` +反例:`mall_management-system / mallManagementSystem` +``` + +### 1.2、目录、文件命名 + +目录、文件名 均以 小写方式, 以中划线分隔。 + +```javascript +正例:`/head-search/`、`/shopping-car/`、`smart-logo.png`、`role-form.vue` +反例:`/headSearch/`、 `smartLogo.png`、 `RoleForm.vue` +``` + +### 1.3、单引号、双引号、分号 + +- html中、vue的template 中 标签属性 使用 **双引号** +- 所有js中的 字符串 使用 **单引号** +- 所有js中的代码行换行要用 **分号** + +## 二、Vue3 组合式 API规范 + +### 2.1、 使用setup语法糖 + +- 组件必须使用 `setup` 语法糖 +- setup 大法方便简洁 +- 全局都要使用setup语法糖 + +### 2.2、组合式Composition API 规范 + +组件内必须使用模块化思想,把代码 进行 拆分; +参照 vue3官方文档对于 Composition Api的理解: [更灵活的代码组织](https://cn.vuejs.org/guide/extras/composition-api-faq.html#better-logic-reuse) ,组合式Api,即 Composition API 解决的是让 相互关联的代码在一起,以更方便的组织代码,故我们的代码格式如下: + +**即:将相关的 变量和代码 写到一起,并使用 行注释 进行分块** + +```js + +``` +举例,分成了两个模块,即: +- 模块1:显示 、隐藏操作的 变量和方法 +- 模块2:表单的 变量和方法 + +**【以下是正确的例子】** + +```js + +``` + +**【错误的例子】** + +```js + +``` + +** vue 官方希望是 模块化的组织代码,你看记得官方这个图吗?** + + + + + + +
+ + +**第一种写法,所有变量写到了一起,就像vue2的 data区域,所有方法写到一起,就像vue2中的 methods区域,这样下来其实和vue2没什么区别,也就语法稍微变了一下,那么就与composition api的初衷违背了**,下面引用官方的话 +>处理相同逻辑关注点的代码被强制拆分在了不同的选项中,位于文件的不同部分。在一个几百行的大组件中,要读懂代码中的一个逻辑关注点,需要在文件中反复上下滚动,这并不理想。另外,如果我们想要将一个逻辑关注点抽取重构到一个可复用的工具函数中,需要从文件的多个不同部分找到所需的正确片段。 + +**SmartAdmin中的写法才真正做到了vue3组合式composition api的意图,每一块业务的变量与方法写到一起,比如上面代码中的`显示与隐藏`的变量和方法放到了一起,`表单`的变量和方法放到了一起**,下面引用官方的话 +> 现在与同一个逻辑关注点相关的代码被归为了一组:我们无需再为了一个逻辑关注点在不同的选项块间来回滚动切换。此外,我们现在可以很轻松地将这一组代码移动到一个外部文件中,不再需要为了抽象而重新组织代码,大大降低了重构成本,这在长期维护的大型项目中非常关键。 + + +### 2.3 模板引用变量Ref + +对于vue3中的模板引用ref,即 ref 是作为一个特殊的 attribute +```html + +``` +我们要求: +- 使用 ref方法,参数为空 进行声明变量 +- 变量必须以 `Ref`为结尾 +- template中的ref 也必须以 `Ref` 为结尾 + +比如上面的例子,我们声明如下 +```js +const inputRef = ref(); +``` + +### 2.4 变量和方法的注释 +在使用Composition Api进行代码编写时,我们有效的组织了代码,但是由于Composition Api变量和方法会写到一起,这时候注释就变得很有必要 +要求: +- 变量必须都加上注释 +- 方法必须加上注释 +比如 +```js + // 查询 公告 默认值 + const queryFormState = { + noticeTypeId: undefined, //分类 + keywords: '', //标题、作者、来源 + documentNumber: '', //文号 + createUserId: undefined, //创建人 + deletedFlag: undefined, //删除标识 + createTimeBegin: null, //创建-开始时间 + createTimeEnd: null, //创建-截止时间 + publishTimeBegin: null, //发布-开始时间 + publishTimeEnd: null, //发布-截止时间 + pageNum: 1, + pageSize: PAGE_SIZE, + }; + // 查询 公告 请求表单 + const queryForm = reactive({ ...queryFormState }); +``` + + +## 三、Vue3 组件规范 + +### 3.1、 组件文件名 +组件文件名应该为 pascal-case 格式 + +正例: + +```javascript +components +|- my-component.vue +``` + +反例: + +```javascript +components +|- myComponent.vue +|- MyComponent.vue +``` + + +### 3.2、 父子组件文件名 +和父组件紧密耦合的子组件应该以父组件名作为前缀命名 +正例: + +```javascript +components +|- todo-list.vue +|- todo-list-item.vue +|- todo-list-item-button.vue +|- user-profile-options.vue (完整单词) +``` + +反例: + +```javascript +components +|- TodoList.vue +|- TodoItem.vue +|- TodoButton.vue +|- UProfOpts.vue (使用了缩写) +``` + + +### 3.3、 组件属性 +组件属性较多,应该主动换行。 + +正例: +```html + +``` + +反例: +```html + +``` + +### 3.4、 模板中表达式 + +组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。复杂表达式会让你的模板变得不那么声明式。我们应该尽量描述应该出现的是什么,而非如何计算那个值。而且计算属性和方法使得代码可以重用。 + +正例: + +```js + + +// 复杂表达式已经移入一个计算属性 +computed: { + normalizedFullName: function () { +​ return this.fullName.split(' ').map(function (word) { +​ return word[0].toUpperCase() + word.slice(1) +​ }).join(' ') + } +} +``` + +反例: + +```js + +``` + +### 3.5、 标签顺序 + +单文件组件应该总是让标签顺序保持为 `