forked from emthink/reactjs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
component-design.md
236 lines (144 loc) · 8.31 KB
/
component-design.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# 通用组件规范指南
定义Tui通用组件开发规范。
## 组件分类
![Component Design](http://image.woshipm.com/wp-files/2017/09/RMinUSUFFcCoDRCyOehm.png)
## 设计原则
组件化 + 模块化 + 规范化 + 工程化是前端领域的四个现代化,而开发通用组件尤其需要注重组件化,模块化,规范化。
### 组件化
组件化即独立,自由组合,组件开发的目标是将局部功能独立抽象出来,然后可以组合多个组件,形成一个完整的应用。就好比为电脑扩充内存条,内存条是独立的,可以随时购买添加,扩充现有内存,然后可以很方便的将其移除,添加至其他电脑,这些过程中,内存条可以很方便的插拔式使用,而且不会影响电脑其他部件的运行。
我们需要尽量保证通用组件的独立,低耦合,高内聚,插拔式可用:
1. 独立:保证与其他组件关联性最小,最小化组件间的相互影响;
2. 低耦合:内部功能和代码高度集中,保证通用组件可以很方便的进行复用;
如,当组件样式依赖于父级组件或页面元素样式时,改变页面样式或组件样式时,很有可能导致组件样式混乱,这不是我们期望的。
3. 插拔式使用:随时可用,随时可移除;
### 模块化
> 模块化编程(modular programming)是一种软件设计技术,它将软件分解为若干独立 的、可替换的、具有预定功能的模块,每个模块实现一个功能,各模块通过接口(输入输出 部分)组合在一起,形成最终程序。
模块化编程在实践中最大的体现就是关注点(SoC,Separation of Concerns)分离:
1. 关注点:系统的某个功能或特性;
2. 分离关注点:分解系统,由若干个独立的单元(模块)组成;
模块化编程就是关注系统各功能点进行模块划分,然后按照模块开发,最后可以通过组合模块构建出系统。
开发通用组件时,需要清楚通用组件应该是作为一个独立功能模块在使用者的系统中存在,所以我们设计通用组件时就需要遵循模块化编程思想。
### 规范化
Tui作为一个开放的云组件库,是期望能被更多的使用者使用,为更多的开发者带来便利,那么它就必须是使用简单,使用方式统一的,只有不会给使用者带来困扰的产品才是好产品,开发通用组件应该遵循本文确定的规范和最佳实践。
## 编码规范
良好的编码习惯和风格,可以一定程度的保证代码的稳定,更重要的是可以让其他开发者更好的理解和使用,所以希望开发通用组件遵循以下的编码规范。
### 命名
#### 名称
1. 所有文档和接口需要使用书面语;
2. 驼峰式命名;
```javascript
// bad
opportunitycontainer or opportunity-container or opportunity_container
// good
opportunityContainer
```
3. 简洁:以英文单词命名时,在保证语义的前提下,尽量简短;
#### 常量/变量命名
1. 变量:变量手字母小写,遵循驼峰式;
2. 常量:大写,可以连字符`_`连接, 如`OPPORTUNITY_TYPES`;
#### 组件命名
1. 组件名:首字母大写,然后遵循驼峰式,如`AppBar`,`EmployeeSelector`;
#### 方法/接口命名
1. 组件内方法或暴露的API名:应望文知义,尽量简短:
```javascript
// bad
add () {}
// good
createOpportunity () {}
```
2. 回调函数:回调函数名以`Callback`为后缀,且参数较多时,包装成json对象返回:
```
// good
successCallback(data)
errorCallback(err)
```
#### 词性
1. 方法名,函数名均为动词(动宾式):
```javascript
// bad
list()
// good
getList() findItem()
```
2. 其他诸如参数,类名,ID名等为名词;
3. bool类型的辅助变量词应以`is`,`has`或`match`开头;
### 格式
1. 代码缩进为2个或4个空格;
2. 统一JavaScript代码风格,语句结束是否添加分号;
### 注释
1. 组件文件顶部注释介绍组件,包括但不限于:
1. `@desc`文件描述;
2. `@author`组件开发作者及邮箱联系方式;
3. 【可选】`@link`组件链接的开源访问地址;
### 样式
1. CSS选择器统一使用class类名;
2. class以分隔符`-`分离,如`.search-form`;
3. 使用组件名作为组件样式的根命名空间,如`Opportunity-content`;
### 目录组织方式
Tui云组件库基本目录组织形式如下:
1. `README.md`:组件说明文档入口;
2. `package.json`:依赖声明;
3. `LICENSE`:授权声明;
4. `index.js`:组件库模块导出文件,支持CommonJs方式引用;
5. `index.es.js`:支持动态import引入方式使用的库模块导出文件;
6. `CHANGELOG.md`:变更记录文档;
7. `style/`:通用样式文件目录;
1. `index.less`:less格式样式文件;
2. `index.css`:css格式样式文件;
3. `index.js`:集中引用管理less样式文件;
4. `css.js`:集中引用管理css样式文件;
8. `umd/`:umd目录,支持umd方式引入使用的版本文件;
9. `es/`:es目录,支持动态import引入使用的组件版本;
10. `lib/`:lib目录,支持CommonJs规范引入使用的组件版本;
#### 单组件模块目录组织
上面介绍的是Tui云组件库的组织目录,接下来介绍具体组件的目录组织形式:
1. `README.md`:组件说明文档入口;
2. `package.json`:依赖声明;
3. `LICENSE`:授权声明;
4. `CHANGELOG.md`:变更记录文档;
5. `index.js`:组件模块导出文件;
6. `style/`:样式组织目录;
1. `index.less`:less格式样式文件;
2. `index.css`:css格式样式文件;
3. `index.js`:集中引用管理less样式文件;
如:
```javascript
import '../../style/index.less';
import './index.less';
```
4. `css.js`:集中引用管理css样式文件;
如:
```javascript
import '../../style/index.css';
import './index.css';
```
7. `xxx.js`:组件模块划分的其他小模块,如`Menu组件,可能会有`MenuList.js`和`Menuitem.js`文件;
#### Menu组件实例
以Menu组件为例,其组织如:
![](http://blog.codingplayboy.com/wp-content/uploads/2018/02/tui-dir-example.png)
### 模块化
组件封装后应同时支持CommonJs规范和UMD方式加载使用,另外尽量支持动态import引入方式使用。
## 组件接口设计规范
我们的组件都是需要以暴露模块接口形式,供开发者使用,所以为了方便开发者的使用和理解,开发通用组件时有必要遵循以下规范。
### 通用规范
1. 兼容性:由于组件的使用环境和场景不可定,所以开发通用组件必须设定组件期望覆盖的兼容设备,并在文档中声明;
2. 安全性:保证组件运行安全,稳定,不会产生危险性输出,和异常;
3. 函数式编程:遵循函数式编程,尽量保证一个接口只负责一个功能,且保证其没有副作用;
### UI设计规范
当开发组件涉及到UI界面时,需要保证适当的样式可控性,提供以下几个属性:
1. `background`:为组件设置背景以适应组件当前所处环境;
### 异常处理
通用组件常常需要给开发者提供一些异常信息,方便开发者追踪问题,解决问题,而不是束手无策:
1. 可以以回调方式在参数中返回异常相关信息;
2. 尽量处理异常,使其不会影响应用的运行;
## 组件文档规范
为了便于其他开发者使用该组件,一个合格的通用组件应该有一份表达良好的API文档。
1. 良好的文档可以帮助使用者快速建立一个关于组件的整体认识,而不需要阅读源码,同时也会提高使用者的使用效率;
2. 文档中应该声明使用组件所需的属性及组件对外暴露出的API,组件的使用者更关心的是如何使用组件,而不是组件如何实现的;
3. 合格的组件文档应该声明组件适配的兼容性情况;
4. 正式的文档应该告诉开发者组件 API 变更以及向后的兼容性情况;
5. `README.md` 应该作为API文档入口文件;
## 参考
1. [前端工程化](https://github.com/fouber/blog/issues/10)
2. [Airbnb JavaScript Style Guide](https://github.com/codingplayboy/javascript)