结对编程(前后端实现) 之 前端篇
Partner:郑伟金 3117004680 👍
GitHub 链接:https://github.com/KofeChen/partner-project
友情链接:https://www.cnblogs.com/ZWJCNBLOG/p/11674592.html
PSP:
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 |
30 |
· Estimate |
· 估计这个任务需要多少时间 |
30 |
30 |
Development |
开发 |
1600 |
1440 |
· Analysis |
· 需求分析 (包括学习新技术) |
100 |
90 |
· Design Spec |
· 生成设计文档 |
30 |
20 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 |
40 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 |
50 |
· Design |
· 具体设计 |
60 |
60 |
· Coding |
· 具体编码 |
1260 |
1060 |
· Code Review |
· 代码复审 |
30 |
30 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
90 |
Reporting |
报告 |
70 |
70 |
· Test Report |
· 测试报告 |
20 |
30 |
· Size Measurement |
· 计算工作量 |
30 |
20 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
20 |
20 |
合计 |
|
1700 |
1540 |
功能分析:
这是一个网页版的小学生四则运算练习系统,共有三个功能:
- 在线做题:点击在线做题按钮,系统会根据用户输入的范围给用户随机生成 10 道题目,用户在做题页面作答并提交,系统会校对答案并在线展示
- 下载离线文件:点击生成离线文件按钮,跳转到题目与答案下载页面,点击题目或者答案下载离线文件
- 上传文件校对答案:点击上传文件对答案按钮,选择文件并上传,系统会显示校对进度,校对完成之后下载按钮就绪可以点击下载
设计实现过程:
接口文档 (部分)
原型设计
作为这个小项目的前端,因为只有前后端两个人,所以前端兼做了设计,根据与后端统一的需求,做出来的实现图如上图。没有原型图,所以是一边完善需求,一边写的页面,简单沿用了同一个界面框的样式。
整个 html 页面分为 Start (开始页面)、Initial (初始化页面)、Practice (在线练习页面)、Download (下载离线文件页面) 和 Upload (上传校对页面) 5个分页
js 代码的话分为 3 个模块分别处理
- Start:开始页面和上传文件进度页面的相关处理
- Initial:初始化页面和下载文件页面的相关处理
- Work:做题页面和在线校对答案以及答案的呈现
代码说明:
下面挑出部分比较有意思的代码进行说明
this.$form.on('change', '#file', function(e) { $(this).clone().replaceAll(_this.file = this) _this.setForm() _this.currentProgress = 0 var clock = setInterval(function() { $.ajax({ url: '/check/rate', type: 'GET', headers: {id: _this.userId} }) .done(function(res) { if (res != '100') { let rate = parseInt(res) if (rate <= 50) { _this.$rate[0].innerText = res + '%' _this.$rightCircle.css('transform', `rotate(${-135+180*rate/50}deg)`) _this.$leftCircle.css('transform', 'rotate(135deg)') } else { _this.$rate[0].innerText = res + '%' _this.$rightCircle.css('transform', 'rotate(45deg)') _this.$leftCircle.css('transform', `rotate(${(135+180*rate/100)}deg)`) } } else if (res === '100') { $('.downLoad h2')[0].innerText = '点击下载' _this.$rate[0].innerText = res + '%' _this.$rightCircle.css('transform','rotate(45deg)') _this.$leftCircle.css('transform', 'rotate(315deg)') _this.$downLoadBtn.addClass('ready') var xhr = new XMLHttpRequest() xhr.open('GET', '/check/answer', true) xhr.responseType = 'blob' xhr.setRequestHeader('id', _this.userId) xhr.onload = function() { if (this.status === 200) { var blob = this.response _this.a = document.createElement('a') _this.a.download = 'Result.txt' _this.a.href = window.URL.createObjectURL(blob) } } xhr.send() clearInterval(clock) } }) .fail(function(err) { console.log(err) }) }, 500) }) }, setForm: function() { var _this = this var form = document.getElementById('uploadForm') console.log(form) var formData = new FormData(form) formData.append('file', $('#file')[0].files[0]) $.ajax({ url: '/check/question', type: 'POST', data: formData, headers: { id: _this.userId }, processData: false, contentType: false }) .done(function(res) { console.log(res) }) .fail(function() { console.log("error..") }) .always(function() { $('#file').replaceWith(_this.file) }) }
上传文件是发送请求中遇到的较为困难的一个:
1、input [type=file] 控件选择同一个文件之后不触发 change 事件,刷新浏览器之后仍不能触发,如果用户选择多次选择相同文件名上传的话会出现文件选择框不弹出来的 bug
原因:因为 input [type=file] 控件的 change 事件是通过 input 输入框中的文本改变来触发事件的,而不是像别的编程语言通过选择文件来触发,这就导致多次选择相同的文件,第一次之后就无法弹出文件选择框;还有浏览器会自动保存 input [type=file] 控件上的文字,页面关闭后打开仍然会恢复原来的文本,这时候选择同路径的文件也不会触发 change 事件。
解决方法:创建一个新的 input [type=file] 控件将旧的替换掉,事件绑定通过事件冒泡来获取
2、提交表单数据,上网找了一下找到了 form 表单封装成 formdata 对象的上传方法,但是会附加额外的信息增加后端处理的负担
后端如何辨别是哪个浏览器发送的文件:
前后端协商之后,决定前端在上传文件之前,先向后台发送请求获取 id 以供后台识别浏览器,然后在请求进度和上传文件时在请求头部设置标识身份的 id 以便后台进行识别。
后端代码测试优化等有兴趣请参考:https://www.cnblogs.com/ZWJCNBLOG/p/11674592.html
页面展示:
开始页面:
在线答题页面:
下载题目页面:
上传校对进度:
在线答题答案卡展示
在线答题答案展示
上传核对答案后的下载文件详情
性能 (后台优化)
(1)10000道题目生成用时 0.068 s
(2)10000道题目核对用时 6.809s(由于为了支持用户自定义题目的核对,故采用了正则表达式进行识别,所以识别花费时间比较多,如果想提高速度可以考虑去除正则匹配以及并行优化)
项目总结:
第一次完整的做网页项目,整个过程包括需求分析与确定、阶段计划、需求调整、预测试、对接口测试以及完善代码,最重要也是收获最多的一个地方是在前后端的沟通协作方面,伙伴很给力也很有实力,使整个开发过程很高效也很愉快,同时也有对原型设计和接口文档规范的认识。
最大的不足之处在于编码过程中,专注实现功能但未能考虑好代码的质量和复用,在很大程度上加重了浏览器的负担。