做为一名前端,我们除了写页面,特效,组件,可能做得最多的要数数据交互了吧,也许有人会说node服务器搭建,后台文件操作,socket.io双向传输,但其实这些归咎于前端更多是因为如今ECMAScript的迅猛发展,多数的前端虽说多少会点但用的其实不是很多,用得多的那些都往全栈走了,又搞前端又搞查数据库字段的那是java,我们吧,可能更多是利用node这个环境,帮我们做一些比如webpack打包,一些异步通讯比如axios等等,而传统上的数据交互,前后端联调是前端一项非常重要的工作。
那前端的数据交互具体是怎样的?
首先大体上的流程差不多是这样:
1、你和后台根据需求先商议好大致需要怎样的数据,格式是怎样(双方都相对比较方便的平衡点,即后台比较好查好存,前端也比较好取,好展示)
2、双方根据协议好的方式各自撸代码,各自先测试。
3、合并后联调。
当然了,这之中还需要解决一些诸如跨域,异步回调等遇到的问题。
目前,我们基于浏览器的通讯主要还是http协议,也有一些其他的比如webSocket(服务端不再是被动接受请求响应,而是主动发起,比如推送消息),而js呢,由于它是单线程的,数据的交互大多数通过异步来实现,比如我们常见的ajax,一些升级版的比如axios,axios比较好的是在于它是基于promise的,promise顾名思义:承诺。我们知道ajax最大的问题是什么呢?所有的操作必须在它的回调函数里才有效果,可能导致一些代码臃肿,不易复用等等。而promise呢,记得看过一些大神的文章,他们对promise的总结很精粹:promise,承诺,犹如古人一诺千金,代表着这个操作我承诺将来会实行,比如我们常见的ajax是这样:
可能jQuery帮我们封装好的ajax在实际开发过程会用得更多,比如说这样:
你想想如果说把所有的操作都写在success里面,甚至第一种情况,成功和失败都写一起,会不会感觉特别的碍眼?代码特别的难看?那如果说,有一种承诺,使得我们可以先执行ajax的请求逻辑,再后面加一些比如ifSuccess(干嘛干嘛...)ifFail(干嘛干嘛),看上去是不是会舒服一些?因为它的承诺,它承诺将来如果怎样怎样,它就会执行怎样怎样,而我们不必掉进回调的深渊(类似于ajax嵌套),是不是在逻辑思维的线索上更直观更利于我们理顺思路?
好了,不管是ajax还是基于promise的axios,不就是数据交互的基础设施嘛,用哪个其实都差不多,而有了第一步的基础设施,我们还需要第二步——数据,目前最常见的数据格式是json,也有一些字符串(咱后面的例子就用个字符串来展示哈)。
而这个过程我们需要知道什么?或者说需要储备怎样的知识?简单来说其实就是json数据解析,字符串处理,正则匹配等等吧(其实不难)。比如说,给到你的数据是这样的:
或者说甚至是这样的:
这些数据可能是你们本公司的,也可能是调用别人接口返回的(比如说上面这种string,作为前端的你是不是很想把返回这种数据给你的人狠狠揍一顿?因为最终展示出来的是这样的。)
当然了,实际工作中一些坑你需要去填,你遇到的数据格式类型可能千奇百怪,但都只能靠你的双手去敲,现在用vue对数据交互就特别的友好,移植复用非常的方便,当然了,说到vue,它这种双向数据绑定,数据劫持的方式原理是怎样的?假如让你用原生js或是jQuery写一个简单的双向绑定demo(比如说你发微博的时候发多少字下面都有一个实时的提示说还差几个字),你又得怎么实现?Angular也是双向绑定的,原理上又有什么不同?这些其实对于每一个用vue开发的使用者而言都是必须要知道的。
有了基础设施(js异步,xhr,http),有了数据与前后台的约定(json),那还差什么呢?仅对于前端而言,就差实现了,利用UI设计的界面,以及一些你所擅长的特效,以及多个平台的兼容,最终实现你想要的效果。前端嘛,狭义上讲,是MVC经典模式下的view,展现在用户面前的那个界面,用户的各种交互操作时刻影响着他们的体验,而前端是让这种体验越来越好,增强用户粘性的工程师。这个界面可以是网站,可以是成型的系统(比如ERP,OA),更可以是游戏,而这些其实后台能给你的仅仅就是一连串的数据,根据你不同的请求返回给你需要的数据,让你去解析,去展示,去实现最终的产品功能。
好了废话不多扯了,我们通过一些小demo来做做我们的数据交互吧。
这个数据呢上面有提了,是一串字符串,你做测试的时候甚至就弄个txt文档都行。
jQuery跟animate.css呢,请自行百度哈。这个特效啥的不重要,重要的是数据的解析过程,展示过程。
html部分:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>作文自动批阅</title> <link rel="stylesheet" href="../dist/animate.css" type="text/css"><!--动画css--> <link rel="stylesheet" href="css/paperReview.css" type="text/css"><!--样式层--> </head> <body> <div class="paperReview"></div> <script src="../dist/jquery-3.3.1.min.js" type="text/javascript"></script><!--jQuery引入--> <script src="js/paperReview.js" type="text/javascript"></script><!--行为层--> </body> </html>
css部分:
html,body,div,h1,h2,h3,h4,h5,h6{margin:0;padding:0}.dc_c_red{color:#f00}.dc_c_green{color:#008000}.paperReview{width:80%;margin:50px auto}.oAutoE,.wordsE,.gramE{width:100%;margin:5px auto;box-shadow:-2px 2px 10px #333;background-color:#cbfcb8;padding:10px 20px;color:#000}h2{font:18px "华文楷体";color:#f00;font-weight:bold;text-shadow:-1px 1px 3px #ccc}h3{font:15px "华文楷体";padding-left:20px;color:#ff4500}p{padding-left:8em;font:12px "microsoft yahei";line-height:25px}.dc_font{font:18px "华文行楷";margin-left:-5em;display:inline-block}.errDetail{margin-bottom:10px;background:rgba(255,255,255,0.4);border-radius:10px;padding:10px 0}.wordsE h3,.gramE h3{margin-top:10px;margin-bottom:10px}body{overflow-x:hidden}
js部分:
$(function(){ let dcObj = function(){}; dcObj.prototype = { constructor : dcObj, init : function(){ let _self = this; _self.user = 'dorseyCh'; _self.submissionTime = "1900-00-00 00:00:00"; _self.autoEvaluation = { //自动评语 name : "※自动评语※", errWords : "", //单词错误 errGrammar : "", //语法错误 errStructure : "", //篇章结构 smooth : "", //可读连贯 theme : "", //主题思想 autoScore : "" //自动评分 }; _self.wordsErrToRight = { name : "※单词纠错※", summarize :'', err : [ //单词纠错,以每条例句作为一个单元,数据类型为object // { // sentence : "", // errPrompt : "", //纠错提示 : S(拼写错误) U(使用错误) // reference : "", //建议单词 // meaning : "" // // } ] }; _self.grammarErrToRight = { name : "※语法纠错※", summarize : "", err : [ // { // sentence : "", // errPrompt : "", // reference : "", // example : "" // } ] //语法纠错,以每条例句作为一个单元,数据类型为object }; _self.smoothErrToRight = { name : "※连贯纠错※", err : [ //连贯纠错,以每条例句作为一个单元,数据类型为object { sentence : "", errPrompt : "" } ] }; }, strAppend : function(str,ins,loc){ return str.slice(0,loc) + ins + str.slice(loc,str.length); }, //存json changeStr : function(str) { let _self = this; let arr = str.split('*'), //四个模块数据 arrWords = (arr[0].split('>'))[1].split('|'), //单词 arrGrammar = arr[1].split('|'), //语法 arrSmooth = arr[2].split('|'), //连贯性 arrAutoE = arr[5].split('|'); //自动评分 // console.log(arrWords); // console.log(arrGrammar); console.log(arrSmooth); // console.log(arrAutoE); /** * 自动评分模块 * @author : dorseyCh 1092240376@qq.com * @personal-Card : Chasing Dream * */ //自动评分相关字段处理 for(let i = 0; i< 5 ; i ++){ arrAutoE[i] = "<span class='dc_c_green dc_font'>" + arrAutoE[i].replace(/:/,':</span>'); } //存该模块json数据 _self.autoEvaluation.errWords = arrAutoE[0]; _self.autoEvaluation.errGrammar = arrAutoE[1]; _self.autoEvaluation.errStructure = arrAutoE[2]; _self.autoEvaluation.smooth = arrAutoE[3]; _self.autoEvaluation.theme = arrAutoE[4]; _self.autoEvaluation.autoScore = arr[4] + "分"; /** * 单词纠错模块 * @author : dorseyCh 1092240376@qq.com * @personal-Card : Chasing Dream * */ //单词模块错误情况综述 let summarizeArr = arrWords[1].split('^'); _self.wordsErrToRight.summarize = summarizeArr[0] + "单词错误:" + summarizeArr[1] + "拼写错误," + summarizeArr[2] + "使用错误。"; //以每一条详细解析的句子为一个对象,并把结果存入err数组 _self.wordsErrToRight.err=[];//每次取值前清空原有内容 let errWordsPosition = arrWords[0].split('^'); let k = 0; for(let i = 0;i<arrWords.length;i++){ if(i%3 === 2 && arrWords[i+2]!==undefined){ if(i%3 === 2){ arrWords[i] = _self.strAppend(arrWords[i],'</span>',(parseInt(errWordsPosition[k+1])+3)); arrWords[i] = _self.strAppend(arrWords[i],"<span class='dc_c_red'>",(parseInt(errWordsPosition[k])+3)); k+=2; } let obj = { sentence : arrWords[i], errPrompt : arrWords[i+1] === 'S' ? "拼写错误" : "使用错误", //纠错提示 : S(拼写错误) U(使用错误) reference : arrWords[i+2], //建议单词 meaning : "" }; _self.wordsErrToRight.err.push(obj); } } /** * 语法纠错模块 * @author : dorseyCh 1092240376@qq.com * @personal-Card : Chasing Dream * */ let gSummarizeArr = arrGrammar[1].split('^'); _self.grammarErrToRight.summarize = "语法错误数:"+gSummarizeArr[0]; //以每一条详细解析的句子为一个对象,并把结果存入err数组 _self.grammarErrToRight.err=[];//每次取值前清空原有内容 let gErrWordsPosition = arrGrammar[0].split('^'); k = 0; for(let i = 0;i<arrGrammar.length;i++){ if(i%4 === 2 && arrGrammar[i+3]!==undefined){ if(i%4 === 2){ arrGrammar[i] = _self.strAppend(arrGrammar[i],'</span>',(parseInt(gErrWordsPosition[k+1])+3)); arrGrammar[i] = _self.strAppend(arrGrammar[i],"<span class='dc_c_red'>",(parseInt(gErrWordsPosition[k])+3)); k+=2; } let obj = { sentence : arrGrammar[i], errPrompt : arrGrammar[i+1], //纠错提示 : S(拼写错误) U(使用错误) reference : arrGrammar[i+2], //建议单词 example : arrGrammar[i+3] }; _self.grammarErrToRight.err.push(obj); } } /** * 连贯纠错模块 * @author : dorseyCh 1092240376@qq.com * @personal-Card : Chasing Dream * */ }, //取json writeJson : function(select){ select.html(""); let _self = this, //自动评分模块显示 oAutoE = '<div class="oAutoE animated bounceInDown">' + '<h2>'+_self.autoEvaluation.name+'</h2>' + '<p>'+_self.autoEvaluation.errWords+'</p>' + '<p>'+_self.autoEvaluation.errGrammar+'</p>' + '<p>'+_self.autoEvaluation.errStructure+'</p>' + '<p>'+_self.autoEvaluation.smooth+'</p>' + '<p>'+_self.autoEvaluation.theme+'</p>' + '<p><span class="dc_c_red dc_font">自动评分:</span>'+_self.autoEvaluation.autoScore+'</p>' + '</div>'; select.append(oAutoE); //单词纠错模块 let wordsE = '<div class="wordsE animated bounceInLeft">' + '<h2>'+_self.wordsErrToRight.name+'</h2>' + '<h3>'+_self.wordsErrToRight.summarize+'</h3>' + '<div class="wordsEContent"></div>' + '</div>'; select.append(wordsE); let oWords = _self.wordsErrToRight.err; for(let i = 0;i<oWords.length;i++){ let oDiv = '<div class="errDetail animated bounceInRight">' + '<p><span class="dc_c_green dc_font">出错句子:</span>'+oWords[i].sentence+'</p>' + '<p><span class="dc_c_green dc_font">纠错提示:</span>'+oWords[i].errPrompt+'</p>' + '<p><span class="dc_c_green dc_font">建议单词:</span>'+oWords[i].reference+'</p>' + '<p>'+oWords[i].meaning+'</p>' + '</div>'; $('.wordsEContent').append(oDiv); } //语法纠错模块 let gramE = '<div class="gramE animated bounceInRight">' + '<h2>'+_self.grammarErrToRight.name+'</h2>' + '<h3>'+_self.grammarErrToRight.summarize+'</h3>' + '<div class="gramEContent"></div>' + '</div>'; select.append(gramE); let oGram = _self.grammarErrToRight.err; for(let i = 0;i<oGram.length;i++){ let oDiv = '<div class="errDetail animated bounceInRight">' + '<p><span class="dc_c_green dc_font">出错句子:</span>'+oGram[i].sentence+'</p>' + '<p><span class="dc_c_green dc_font">纠错提示:</span>'+oGram[i].errPrompt+'</p>' + '<p><span class="dc_c_green dc_font">建议单词:</span>'+oGram[i].reference+'</p>' + '<p><span class="dc_c_green dc_font">简单举例:</span>'+oGram[i].example+'</p>' + '</div>'; $('.gramEContent').append(oDiv); } }, animate : function(){ //自动评语模块 let oP = $('.oAutoE').children('p'); oP.addClass('animated fadeInRight'); oP.each(function(i){ oP.eq(i).css("animation-delay",(i+4)/5+'s'); }); //单词模块 let errDetail = $('.errDetail'); errDetail.each(function(i){ errDetail.eq(i).css("animation-delay",(i+2)/2+'s'); }); }, run : function(select,str){ this.init(); this.changeStr(str); this.writeJson(select); this.animate(); } }; $.ajax({ type : 'GET', url : 'review.txt', success : function(data){ let obj = new dcObj(); obj.run($('.paperReview'),data); } }); })
咱最后呢,得贴点数据,既然是纯粹的字段,咱用个简单的txt文档存一下吧。
~fc3243a9f2225d47371b4ad13cdfa81c#2018-07-12 09:53:01>19^26^79^85|2^1^1|1. Our time is like a funtuel.|S|funnel, Bunuel|2. His parents come to school to talk with his teachers many times,but it doesn't effect.|U|affect|*11^40|1|1. My View on Computer Games Computer games are not our life.|这个短语重复了,建议改为“Computer Games”。|Computer Games|All we wanted to do was to stand very quietly and look and look and look.| | |*|1^1^2^该句中的短语词“We students”、“much more time”、“meaningful things”在上一句中没有提及,导致句子之间过渡中断。^0-11^25-39^43-60^|1^3^4^该句中的短语词“It”在上一句中没有提及,导致句子之间过渡中断。^0-2^|1^6^7^该句中的短语词“computer games”、“our health”、“we”在上一句中没有提及,导致句子之间过渡中断。^8-22^34-44^45-47^|1^8^9^该句中的短语词“a bad thought”在上一句中没有提及,导致句子之间过渡中断。^7-20^|1^9^10^该句中的短语词“I”、“a classmate”、“Tom”在上一句中没有提及,导致句子之间过渡中断。^0-1^7-18^25-28^|1^14^15^该句中的短语词“So many examples”、“us”、“much time”、“computer games”在上一句中没有提及,导致句子之间过渡中断。^0-16^34-36^50-59^63-77^|**77.3*单词错误:有较少单词错误,请注意单词的记忆学习。|语法错误:有少量语法错误,请注意语法知识的学习。|篇章结构:段落数不够,通常短文结构分三段较好;句子数太多,请注意写作句子数要求;短语数不够,请适当增加短语的使用;单词数太多,请注意写作字数要求;句子结构有较好的多样性;使用了较为容易的单词;词汇有较好的丰富性。|可读连贯:具有较好可读性;文字勉强连贯,第1段基本连贯。|主题思想:不切题;有些地方主题思想与表达不清。|~
当然了,对于字符串的匹配,如果规则不是比较复杂的话,其实一句正则就可以搞定,大神都是用正则的,像我这样的菜鸟当然是只能用点不算正则的正则哈= =
(原创首发于慕课网)