@@ -107,7 +107,7 @@ getData() {
107
107
const templateType = this.typeRefMap[this.indexForm.type];
108
108
const validate1 = this.$refs["indexForm"].validate();
109
109
const validate2 = this.$refs[templateType].vaildate();
110
- 父子表单一起验证
110
+ // 父子表单一起验证
111
111
Promise.all([validate1, validate2])
112
112
.then(res => {
113
113
// 都通过时,发送请求
@@ -135,145 +135,6 @@ getData() {
135
135
136
136
从** 工作流程和项目的痛点** 出发,** 你会在实践、总结并解决实际问题中进步的更加迅速** 。
137
137
138
-
139
- ## 背景
140
- 当我们在做后台管理系统时,经常会遇到非常复杂的表单:
141
- > + 表单项非常多
142
- > + 在各种表单类型下,显示不同的表单项
143
- > + 在某些条件下,某些表单项会关闭验证
144
- > + 每个表单项还会有其他自定义逻辑,比如** 输入框可以插入模板变量、输入字符数量显示、图片上传并显示、富文本** 。。。
145
- > + 在这种错综复杂的情况下,完成表单的验证和提交
146
- > + [可以查看具体例子](https: // kevinlij.github.io/Verification-of-complex-forms/):例子中省略了很多琐碎的功能,只保留整体的复杂表单框架,用于展示解决方案
147
-
148
- ## 方案1 : 在一个` vue` 文件中
149
- 所有的表单项显示隐藏、验证、数据获取、提交、自定义等逻辑放在一起
150
- > + 根据表单类型,使用` v-if/v-show` 处理表单项显示隐藏
151
- > + 在` elementui` 自定义验证中,根据表单类型,判断表单项是否验证
152
- > + 根据表单类型,获取不同的数据,并提交到不同的接口
153
- > + 其余所有的自定义逻辑
154
-
155
- #### 缺点
156
- + 乱
157
- + 乱
158
- + 还是乱
159
- + 一个` vue` 文件,轻轻松松上` 2000` 行
160
- + 在我尝试加入一种新的表单类型时,我发现我已经无。从。下。手。
161
-
162
-
163
- ## 方案2 :分离组件
164
- > 其实很容易想到** 根据不同的表单类型,分离出多个相应类型的子表单** 。但我在实践时还是遇到了很多问题:** 父子表单验证、整体提交数据的获取** 等等,并总结出一套解决方案:
165
-
166
- ### 1. 子组件
167
- 所有的子组件中都需要包含两个方法` validate` 、` getData` 供父组件调用。
168
-
169
- #### (1 ) ** ` validate` 方法**
170
- 用于验证本身组件的表单项,并返回一个` promise` 对象
171
- ` ` ` js
172
- vaildate() {
173
- // 返回` elementUI` 表单验证的结果(为` promise` 对象)
174
- return this.$refs["ruleForm"].validate();
175
- },
176
-
177
- ` ` `
178
- #### (2 ) ** ` getData` 方法**
179
- 提供子组件中的数据
180
- ` ` ` js
181
- getData() {
182
- // 返回子组件的form
183
- return this.ruleForm;
184
- },
185
- ` ` `
186
-
187
- ### 2. 父组件
188
-
189
- #### (1 ) [策略模式](https: // www.cnblogs.com/xiaohuochai/p/8029651.html)
190
- 使用策略模式存储并获取** 子表单的` ref` ** (用于获取子表单的方法)和** 提交函数** 。省略了大量的` if-else` 判断。
191
-
192
- ` ` ` js
193
- data:{
194
- // type和ref名称的映射
195
- typeRefMap: {
196
- 1: "message",
197
- 2: "mail",
198
- 3: "apppush"
199
- },
200
- // type和提交函数的映射。不同类型,接口可能不同
201
- typeSubmitMap: {
202
- 1: data => alert(` 短信模板创建成功${JSON .stringify (data)}` ),
203
- 2: data => alert(` 邮件模板创建成功${JSON .stringify (data)}` ),
204
- 3: data => alert(` push模板创建成功${JSON .stringify (data)}` )
205
- },
206
- }
207
- ` ` `
208
-
209
- #### (2 ) ** ` submit` 方法**
210
- 用于** 父子组件表单验证、获取整体数据、调用当前类型提交函数提交数据**
211
- > ** 因为` elementUI` 表单验证的` validate` 方法可以返回` promise` 结果** ,可以利用` promise` 的特性来处理父子表单的验证。
212
- 比如[` then` 函数可以返回另一个` promise` 对象](https: // juejin.im/post/5cc17448f265da0379417cfc#heading-0)、[`catch`可以获取它以上所有`then`的`reject`](https://juejin.im/post/5cc17448f265da0379417cfc#heading-1)、[`Promise.all`](https://juejin.im/post/5cc17448f265da0379417cfc#heading-6)。
213
-
214
- + 父表单验证通过才会验证子表单,存在先后顺序
215
- ` ` ` js
216
- // 父表单验证通过才会验证子表单,存在先后顺序
217
- submitForm() {
218
- const templateType = this.typeRefMap[this.indexForm.type];
219
- this.$refs["indexForm"]
220
- .validate()
221
- .then(res => {
222
- // 父表单验证成功后,验证子表单
223
- return this.$refs[templateType].vaildate();
224
- })
225
- .then(res => {
226
- // 全部验证通过
227
- // 获取整体数据
228
- const reqData = {
229
- // 获取子组件数据
230
- ...this.$refs[templateType].getData(),
231
- ...this.indexForm
232
- };
233
- // 获取当前表单类型的提交函数,并提交
234
- this.typeSubmitMap[this.indexForm.type](reqData);
235
- })
236
- .catch(err => {
237
- console.log(err);
238
- });
239
- },
240
- ` ` `
241
- + 父表单,子表单一起验证
242
- ` ` ` js
243
- submitForm1() {
244
- const templateType = this.typeRefMap[this.indexForm.type];
245
- const validate1 = this.$refs["indexForm"].validate();
246
- const validate2 = this.$refs[templateType].vaildate();
247
- // 父子表单一起验证
248
- Promise.all([validate1, validate2])
249
- .then(res => {
250
- // 都通过时,发送请求
251
- const reqData = {
252
- ...this.$refs[templateType].getData(),
253
- ...this.indexForm
254
- };
255
- this.typeSubmitMap[this.indexForm.type](reqData);
256
- })
257
- .catch(err => {
258
- console.log(err);
259
- });
260
- },
261
- ` ` `
262
-
263
- #### 查看[在线项目](https: // kevinlij.github.io/Verification-of-complex-forms/)、[项目github](https://github.com/kevinLiJ/Verification-of-complex-forms)和[组件代码](https://github.com/kevinLiJ/Verification-of-complex-forms/tree/master/src/components)
264
-
265
- > 总结:很多项目我都遇到这种复杂的表单,也用了很多种解决方案,在此总结出了一种比较整洁简便的方案。当然还有其他很多方案,比如** 可以把数据提交的方法放在每一个子组件中,公共的表单项数据通过` props` 传递给子组件用于提交** 。有其他更加简洁的方案,欢迎评论,或者[` github` 上提` issue` ](https: // github.com/kevinLiJ/Verification-of-complex-forms/issues)
266
-
267
- -- -
268
-
269
- > 题外话: 看了[前端架构师亲述:前端工程师成长之路的 N 问 及 回答](https: // juejin.im/post/5d0ba00af265da1bc7524043#heading-3)中的几个回答后,对我有很大的启发。在**对自己的技术方向、前景迷茫时、或者在埋怨自己的项目太low时、或者埋怨自己每天在做重复工作时、或者每天对层出不穷的新技术焦头烂额时**,不妨**认真的审视下自己的项目**,
270
- > + 每天重复的工作,是不是可以自己造轮子了;
271
- > + 技术栈太low,是不是可以平滑过渡到新技术,提高开发效率;
272
- > + 学再多的新技术,最终也会回归并实践到项目中。
273
-
274
- > 从** 工作流程和项目的痛点** 出发,** 你会在实践、总结并解决实际问题中进步的更加迅速** 。
275
-
276
-
277
138
-- -
278
139
279
140
> 写这篇文章的感受:** 把这些东西表达出来的难度 ` >>` 文章本身所包含的技术难度**
0 commit comments