# 开发规范 - [开发规范](#开发规范) - [规范宗旨](#规范宗旨) - [命名问题](#命名问题) - [命名需要具有实义](#命名需要具有实义) - [文件命名](#文件命名) - [界面层文件](#界面层文件) - [数据控制层文件](#数据控制层文件) - [组件文件](#组件文件) - [请求文件](#请求文件) - [样式命名](#样式命名) - [界面样式](#界面样式) - [组件样式](#组件样式) - [JS 变量和属性的命名](#js-变量和属性的命名) - [变量命名的特别约定](#变量命名的特别约定) - [JS 方法的命名](#js-方法的命名) - [在数据控制层](#在数据控制层) - [在组件内](#在组件内) - [书写问题](#书写问题) - [JS 中的书写](#js-中的书写) - [变量定义符](#变量定义符) - [模版中的函数调用](#模版中的函数调用) - [CSS 属性顺序](#css-属性顺序) ## 规范宗旨 **代码首先是给人读的,其次才是给机器运行**,所以让代码容易阅读是应尽的责任 除了尽可能不写难懂的代码外,我们还需要尽量遵守统一的规范,来帮助我们更高效率的相互阅读代码 ## 命名问题 ### 命名需要具有实义 命名的核心原则是名称含有具体的实体含义 比如没有实义的 ```js const onClick = () => null; // 不好的命名 ``` 因为 `click` 可以发生在任何元素上,从这个名称上无法分辨业务种类,所以我们认为这个函数名没有实义,需要改进一下: ```js const onProductSelected = () => null; // 良好的命名 ``` 改进后,从函数名一看便知,这是商品被选中了以后的需要进行的操作,又因为具备了在同一个页面的唯一性,能帮我们快速获取信息,知道这是哪个业务的哪个环节,大幅提高阅读效率,这就是实义 ### 文件命名 常用文件命名约定 #### 界面层文件 界面层文件(.vue、.scss),采用小驼峰命名 ``` index.vue index.scss ``` #### 数据控制层文件 数据控制层文件(.js),以固定前缀 P 开头,再接大驼峰 ``` PIndex.js ``` 数据层代码定义的名称,需要和文件名一致 ```js export class PIndex extends Pilot {} ``` #### 组件文件 不论是公共组件还是页面子组件(.vue、.scss),都以固定前缀 C 开头,再接大驼峰 ``` CMenu.vue CMenu.scss ``` 组件代码定义的名称,需要和文件名一致 ```js // CMenu.vue 的组件名,必须是 CMenu export default { name: 'CMenu', } ``` #### 请求文件 请求层文件(.js),以固定前缀 F 开头,再接大驼峰 ``` FCommon.js ``` 请求集合的代码定义名称,需要和文件名一致 ```js // FCommon.js 的类名称,必须是 FCommon class FCommon extends Fetcher {} // FCommon.js 代表的类的实例名称,则是 $fetchCommon export const $fetchCommon = new FCommon(); ``` ### 样式命名 样式名的命名,采用横杠连接 ```css .page-name {} ``` #### 界面样式 任何一个界面必定包含众多样式,所以: * 最父级样式名固定,与界面名称一直 * 中间层,需要以父级为前缀,接板块说明 * 末端则可单名,且尽量不含实义 ```css /** 在界面 userList.vue 中,最父级样式名名称固定 **/ .user-list { /** 中间多层,以父级为前缀 **/ .user-list-title { /** 末端可单名,尽量非实义 **/ .left, .text, .icon, .sub, .close {} } } ``` #### 组件样式 组件样式名必须已 `c-` 开头,最父级样式名必须与组件名挂钩 例如,组件 CMenu.vue 中,最父级样式名必须是: ```css .c-menu {} ``` ### JS 变量和属性的命名 使用小驼峰,注意不能以动词开头 ```js // 变量 const name = ''; const orderList = ''; // 属性 const user = { name: '', lastOrder: '', }; ``` #### 变量命名的特别约定 **变量名允许 is 开头** 变量名不能用动词开头,但是允许 is 作为特例 ```js // 允许 is 开头的变量名 let isOpened = false; ``` **事件变量用 evt** 事件 event 的简写,必须是 evt(不能用单字母 e ) ```html ``` **报错信息用 err** 报错 error 的简写,必须是 err(不能用单字母 e ) ```js Taro.request({ fail: err => {}, }); ``` **后端数据 res** 后端返回数据,优先采用 resource 的简写 res ```js $fetch.getEquipments().then(res => {}); ``` ### JS 方法的命名 #### 在数据控制层 **提供给界面层使用的方法,用 on 开头** ```js // 数据控制层定义 onOpenOrderDetail() {} ``` ```html // 界面层使用 ``` **数据层自用的方法,用下划线开头** ```js // 数据控制层定义 _checkOrderDetailOpened() {} onOpenOrderDetail() { // 数据控制层内部自用 this._checkOrderDetailOpened(); } ``` #### 在组件内 **接收父级方法的时候,用 on 开头** ```js export default { props: { // 选择会员后的回调 onUserSelected: Function, }, } ``` **组件自身模版绑定的时候,用 handle 开头** ```js export default { methods: { // 组件层定义 handleUserSelected() {} } } ``` ```html // 组件层自身模板绑定 ``` **函数相互调用的时候,用下划线开头** ```js export default { methods: { // 组件层定义 _checkUser() {}, handleUserSelected() { // 组件层内部自用 this._checkUser() } } } ``` **给父级ref的引用进行调用的方法,使用 $ 开头** ```js export default { methods: { // 组件层定义 $close() {} } } ``` 父级 ```html ``` ```js onCloseAll() { // 父级 ref 调用 this.$refs.userDetail.$close() } ``` ## 书写问题 书写规则都由编辑器自动格式化即可,这里主要说明非格式化的几点约定 ### JS 中的书写 #### 变量定义符 弃用 `var` ,改用 `const` 与 `let` ,且优先使用 `const` ,除非要改值 ```js const name = 'Tevin'; ``` ```js let count = 0; count++; ``` 注意,const 定义的对象,其属性是可以改值的 ```js const search = { count: 1 }; search.count++; // 允许运行 search = {}; // 报错 ``` 所以: * 对于普通数据,如果明确要变更变量值,才使用 `let` * 对于引用数据,如果明确需要重新赋值一个引用对象,才使用 `let` #### 模版中的函数调用 模版中调用函数,必须显式的书写 evt 变量和箭头函数,即: `evt => fncName()` 我们把 Taro 自身组件视为普通元素,元素绑定事件使用 `@tap` 的方式,非元素皆是组件,组件使用 `:onClick` 的方式绑定 例如: ```html ``` ### CSS 属性顺序 为了避免 css 属性写重复,请按如下顺序书写: * **文档流属性** display, position, float, clear, visibility, table-layout 等 * **大小属性** width, height, margin, padding 等 * **文字排版属性** font, line-height, text-align, text-indent, vertical-align 等 * **装饰性属性** color, background, border, opacity, shadow, cursor 等 * **生成内容属性** content, list-style, quotes 等 * **二次渲染属性** zoom, transform 等 * **动画属性** transition, animation 等