本文由 IMWeb 社区 imweb.io 授权转载自腾讯内部 KM 论坛,原作者:easonruan。点击阅读原文查看 IMWeb 社区更多精彩文章。
笔者目前正在开发一个涉及较多表单的场景的新项目。但由于是新项目进度赶,产品人员紧缺,表单需求往往没有考虑得很周全。
那作为一名前端开发,如何辅助产品尽可能让表单需求一次即通关,减少反复沟通以及提缺陷修缺陷的时间,从而加快项目进度?
以下是笔者在项目中在表单开发方面的一些总结:
以下演示案例为vue项目,组件库为element-ui
业务场景:
表单中如果涉及手机号码,因为手机号码是特殊场景,我们很容易想到特殊的校验规则——手机号的正则校验。
然而对于一个通用型字段,如标题 title 、描述 desc 等基本的字段,它们实在太普通太一般,导致我们放松了警惕。
导致问题:开发与测试反复在 tapd
提缺陷修缺陷,在一堆小问题上浪费了大量时间,工作效率低。
解决方法:
// form rulesexport default { title: [ /** * Tips 避免用户的输入前后有空格 * 可以使用 v-model.trim 指令自动清除用户前后空格, * 技术手段能解决的,我们避免提示用户 **/ { max: 50, message: '不能超过50个字', trigger: 'blur' }, { pattern: /^[\u0020-\u007E \u4E00-\u9FA5 \uFF00-\uFF61 \u2000-\u202F \u3000-\u3017]+$/, // \u0020-\u007F 基本拉丁字母 https://unicode-table.com/cn/blocks/basic-latin/ // \u4E00-\u9FA5 中文 https://unicode-table.com/cn/blocks/cjk-unified-ideographs/ // \uFF00-\uFF61 半角及全角形式字符 https://unicode-table.com/cn/blocks/halfwidth-and-fullwidth-forms/ // \u2000-\u202F 英文标点 https://unicode-table.com/cn/blocks/general-punctuation/ // \u3000-\u3017 中文标点 https://unicode-table.com/cn/blocks/cjk-symbols-and-punctuation/ message: "不能包含特殊字符", trigger: "blur" } ]}
业务场景:当用户快速点击提交按钮,导致问题:页面会重复发请求给后端。
解决方法虽然很简单,但这却是开发最容易忽略的,也是tapd上最经常见的缺陷问题。
解决方法一: 在业务代码执行完之前不能再次触发
export default { methods: { onSubmit () { // 可以与Loading搭配使用 if (this.isCommitting) return; this.isCommitting = true;
// 表单验证以及业务请求代码
this.isCommitting = false; }, }}
解决方法二: 经过评论的提醒,遗漏了利用 debounce
防抖实现防二次点击操作。
export default { mounted() { // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。 this.debouncedSaveForm = _.debounce( this.onSubmit, // 回调函数 500, // 时间窗口的间隔 { leading: true, // 点击立即执行 trailing: false // 延迟时间过后不执行 } ); }, methods: { onSubmit () { if (this.isCommitting) return; this.isCommitting = true;
// 表单验证以及业务请求代码
this.isCommitting = false; }, }}
业务场景:表单提交后没展示Loading导致问题:当请求request较久时,页面像是卡死了,没任何响应,用户体验很差。
业务场景:遇到错误时没隐藏Loading导致问题:当请求request出错时,Loading没关闭,页面流程进行不下去。
解决方案:
export default { methods: { onSubmit () {
// 容易忽略一:发送请求前,没展示Loading this.$loading.show('努力加载中...'); request('apiUrl', data) .then(() => {}) .catch(err => { // 容易忽略二:请求出错时,没隐藏Loading this.$loading.hide(); })
}, }}
业务场景:如果表单是属于弹窗 Dialog 内,部分开发为了代码可复用性,新增和编辑是共用同一个表单代码。
导致问题:用户在编辑某一条数据后,再点击新增,会发现新增表单里面的内容是上一条编辑内容的数据。
解决方案:
export default { mounted() { // 页面初始化时,先备份表单数据 this._bak_form = _.cloneDeep(this.form); }, methods: { onOpenDialog(actionType, tableRowIndex, data) { if (actionType === "add") { // 新增时,需要恢复为默认数据 this.form = _.cloneDeep(this._bak_form); /** * Tips * 这里不能用解构 this.form = {...this._bak_form}, * 不然会导致,改了form里面的(object或array类型)数据,同时会影响到_bak_form的数据 * 这是因为引用数据类型的指针还是指向同一个地址。 **/ } else if (actionType === "edit") { // 编辑 this.tableRowIndex = tableRowIndex; this.form = _.cloneDeep(data); } this.actionType = actionType; this.visible = true; }, }}
Tips 避免在关闭窗口时恢复为默认数据
resetFields
将所有字段值重置为初始值并移除校验结果(但不能解决点编辑后再点新增时,恢复为默认数据)业务场景:当用户在填写一个长表单时,手误点了关闭页面或者点击去到其他页面。
导致问题:用户花时间填写的表单数据会丢失,用户又要重新填一遍。用户体验大大降低。
解决方法:
export default { watch: { "visible": value => { if (!value) { // 当弹窗关闭不涉及表单时,清除事件 window.onbeforeunload = null; return; } // 当弹窗显示有表单数据时,网页跳转或者关闭时提醒用户 window.onbeforeunload = e => (e.returnValue = "确定离开当前页面?"); } },}
最后,我汇总一下上面5个技巧点的真实场景Demo:
https://codepen.io/ryqsky
以上都不是什么新内容,但如果工作中能重视并注意到这些细节问题,就能一次即通关表单开发需求,减少与产品测试反复沟通的时间,加快项目的进度。
不然等到产品或测试临下班前发现这些问题时,会出现这样的场景:开发被拖着对着屏幕敲代码修缺陷,测试重新打开缺陷,反复循环N次。
N=上面提到的5个技巧点
中华人民共和国消防法第二条是 “消防工作贯彻预防为主,防消结合的方针”
,放在需求开发上也是一样道理:**提前发现提前修复才能避免当代码发生“火灾”时的一团乱。
IMWeb 团队隶属腾讯公司,是国内最专业的前端团队之一。
我们专注前端领域多年,负责过 QQ 资料、QQ 注册、QQ 群等亿级业务。目前聚焦于在线教育领域,精心打磨 腾讯课堂 及 企鹅辅导 两大产品。
社区官网:
http://imweb.io/
加入我们:
https://hr.tencent.com/position_detail.php?id=45616
扫码关注 IMWeb前端社区 公众号,获取最新前端好文
微博、掘金、Github、知乎可搜索 IMWeb 或 IMWeb团队 关注我们。
👇点击阅读原文获取更多参考资料