你是否发现项目中有很多页面只用到了框架不到十分之一的内容,还引了压缩后还有70多kb的jquery库
你是否发现项目中就用了两三个underscore提供的方法,其他大部分的你方法你甚至从来没有看过
你是否发现fetch好像比ajax好用那么一点
你是否想过自己封装个ajax....
纯前端写得久了,便想折腾点事情。比如先定一个小目标,年前自己写个类jquery轻量级库....
那么就从自己封装一个ajax切入吧,首先我整理的一个流程图,一目了然

解析参数数据

通常我们的请求后面会有一些参数,如果是get请求当然可以直接通过'&'拼在url后面。那么post就需要做一下处理了,如果参数是字符串,则将字符串用‘&’符号切割转化成键值对形式,同时用encodeURIComponent转码,最后类似于jquery的处理,将/%20/g(空格)替换成'+'。
      getData: function(){varname, value;if(opts.data) {if (typeof opts.data === "string") {opts.data= opts.data.split("&");for (var i = 0, len = opts.data.length; i < len; i++) {name= opts.data[i].split("=")[0];value= opts.data[i].split("=")[1];opts.data[i]= encodeURIComponent(name) + "=" +encodeURIComponent(value);}opts.data= opts.data.replace("/%20/g", "+");}else if (typeof opts.data === "object") {var arr =[];for (var name inopts.data) {var value =opts.data[name].toString();name=encodeURIComponent(name);value=encodeURIComponent(value);arr.push(name+ "=" +value);}opts.data= arr.join("&").replace("/%20/g", "+");}//使用GET方法或JSONP,则手动添加到URL中if (opts.type === "GET" || opts.dataType === "jsonp") {opts.url+= opts.url.indexOf("?") > -1 ? opts.data : "?" +opts.data;}}},

创建jsonp

如果dataType为jsonp的话,其实我们就可以理解为不是ajax请求了,而是伪造了一个script标签,通过script的src属性相当于发起了一个请求,其中带了一个callback(这里是名称叫jsonp_timeName)的参数,最终约定好后台的数据包通过jsonp_name(data)这种形式包裹起来,这样就相当于前端再回调了一个jsonp_name的方法,将数据通过参数的形式带过来了,所以前端js需要实现一个名叫jsonp_name的方法。其实jsonp跨域的方法有很多种,比如还有伪造iframe等,跨域详情解决方案可以参考我的博文 http://www.cnblogs.com/liliangel/p/5760426.html
      createJsonp: function(){var script = document.createElement("script"),timeName= new Date().getTime() + Math.round(Math.random() * 1000),callback= "jsonp_" +name;window[callback]= function(data) {clearTimeout(ajax.options.timeoutFlag);document.body.removeChild(script);try{data&& (data =JSON.parse(data));}catch(e) {console.error('ajax error for json parse responseText');}  ajax.success(data);}script.src= url +  (url.indexOf("?") > -1 ? "" : "?") + "callback=" +callback;script.type= "text/javascript";document.body.appendChild(script);ajax.timeout(callback, script);},

创建XHR

首先通过兼容性处理的getXHR()方法得到xhr对象,接着设置请求头,区分post、get。每当 readyState 改变时,就会触发 onreadystatechange 事件,readyState 属性存有 XMLHttpRequest 的状态信息。这里我相当于重写readystate事件监听,来做我自己的相应逻辑处理,由于执行abort()方法后,有可能触发onreadystatechange事件,所以设置一个ajax.options.timeoutBool标识,来忽略中止触发的事件。最后调用xhr的send()方法发送出请求,同时渲染timeout()方法。

    createXHR: function(){//创建对象xhr =ajax.getXHR();xhr.open(opts.type, opts.url, opts.async);//设置请求头if (opts.type === "POST" && !opts.contentType) {//若是post提交,则设置content-Type 为application/x-www-four-urlencodedxhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");}else if(opts.contentType) {xhr.setRequestHeader("Content-Type", opts.contentType);}//添加监听xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if (opts.timeout !==undefined) {//由于执行abort()方法后,有可能触发onreadystatechange事件,所以设置一个ajax.options.timeoutBool标识,来忽略中止触发的事件。if(ajax.options.timeoutBool) {return;}clearTimeout(ajax.options.timeoutFlag);}if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {var responseText =xhr.responseText;try{xhr.responseText&& (responseText =JSON.parse(responseText));opts.success(responseText);}catch(e) {console.error('ajax error for json parse responseText');//opts.error(xhr);
}           }else{opts.error(xhr);}}};//发送请求xhr.send(opts.type === "GET" ? null: opts.data);ajax.timeout();//请求超时}

兼容IE6

获取xhr对象可能会存在低版本ie兼容性问题,为此这样判断处理一下
      getXHR: function(){if(window.XMLHttpRequest) {return newXMLHttpRequest();}else{//遍历IE中不同版本的ActiveX对象var versions = ["Microsoft", "msxm3", "msxml2", "msxml1"];for (var i = 0; i < versions.length; i++) {try{var version = versions[i] + ".XMLHTTP";return newActiveXObject(version);}catch(e) {console.log('error ajax',e)}}}}

设置请求超时

前面我定义了一个全局的属性timeoutFlag,这里通过settimeout延时函数给它赋值。如果是jsonp,则移除原来追加的script标签,否则通过全局的xhr条用abort()方法终止正在发送的请求!

    timeout: function(callback, script){if (opts.timeout !==undefined) {ajax.options.timeoutFlag= setTimeout(function() {if (opts.dataType === "jsonp") {deletewindow[callback];document.body.removeChild(script);}else{ajax.options.timeoutBool= true;xhr&&xhr.abort();}}, opts.timeout);}},

全局变量

var defaultOpts ={url:'', //ajax 请求地址type : 'GET', //请求的方法,默认为GETdata : null, //请求的数据contentType : '',//请求头dataType : 'json', //请求的类型,默认为jsonasync : true, //是否异步,默认为truetimeout: 5000, //超时时间,默认5秒钟before : function() {console.log('before')},//发送之前执行的函数error: function() {console.log('error')},//错误执行的函数success: function() {console.log('success')}//请求成功的回调函数
}for (i indefaultOpts) {if (opts[i] ===undefined) {opts[i]=defaultOpts[i];}}var xhr = null;options: {timeoutFlag:null, //超时标识timeoutBool: false //是否请求超时},

初始化调用

我这里是用面向对象函数方式写的,核心初始化代码如下:
init: function(){opts.before();ajax.getData();opts.dataType=== "jsonp" ?ajax.createJsonp() : ajax.createXHR();},ajax.init();

设置AMD等规范

如果是用requireJS这种方法引用,那么还需要设置一下amd、cmd或者commonJs规范
//AMD && CMDif(typeof define === 'function'){define(function(){returnli;});//CommonJS}else if(typeof module !== "undefined" && module !== null){module.exports=li;//window}else{window.li=li;}

调用示例

调用示例,我这里只贴出异步的方式,当然还有好几种情况,比如出错等,这里不一一展示

默认为gety异步请求,超时时间5秒钟。before为请求前执行的函数,通常我们可以写统一的loading动画。当发生405/500等这种错误时,会调用error方法,当然我们通常在success回调函数里做逻辑处理。这里尽量跟jquery库的ajax封装保持一致,是为了更符合原有的开发编码习惯

结果

控制台输出如下:

我这里用$这个符合作为全局对象引入,也是为了更符合原来用jquery的编码习惯,但是这里只实现了其中的ajax方法哦,其他项目中高频出现的方法,以及常用的小组件后续慢慢补充....
代码已上传github https://github.com/helijun/component/tree/master/li

转载于:https://www.cnblogs.com/liliangel/p/6163994.html

先定一个小目标,自己封装个ajax相关推荐

  1. Java学习|先定一个小目标比如让行为聚焦

    2019独角兽企业重金招聘Python工程师标准>>> 版权声明:本文为北京尚学堂原创文章,未经允许不得转载.​ 如果你想达成一个结果,而且保持效率和质量,就必须让自己行为聚焦到一点 ...

  2. 【科技百咖】人大金仓:先定一个小目标,比如做中国No.1的数据库

    自身的强大内力才是制胜一切的关键 自中美贸易摩擦开始,国内就悄然兴起了一股「王牌热」,大家纷纷在各个角度寻找中国制胜美国的各种「王牌」.但在人大金仓总裁杜胜的心中,真正的王牌还是「内力」,自身的强大内 ...

  3. 【先定一个小目标】数据挖掘学习进度总结

    1 数据可视化 pandas df.head() 看前几行 df.value_counts() 看总体分布 df.info()/df.describe() 看缺失值.整体情况 df.plot(kind ...

  4. 关于“先定一个小目标,比如挣它一个亿”

    王健林有一次在采访里说过这句话"先定一个小目标,比如挣它一个亿" 这句话的确挺有意思,起初我只是把它当作段子来看的. 最近在学习python,我发现学习的这个过程,也需要有明确的目 ...

  5. 先定一个小目标:10天自学C语言编程,教你如何改变一生

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  6. 吴云坤:先定一个小目标,让网络安全具有智能

    前言 忽如一夜春风来!本周有一个王健林的采访视频刷爆了朋友圈,无独有偶,他谈小目标的话音还未落,同一天360网神集团总裁吴云坤,也定了一个小目标,一个能达到的小目标:"让网络安全具有智能&q ...

  7. Redola.Rpc 的一个小目标:20000 tps

    Redola.Rpc 的一个小目标 Redola.Rpc 的一个小目标:20000 tps. Concurrency level: 8 threadsComplete requests: 20000 ...

  8. 2019,先定个小目标

    说来惭愧自己一直没有写文章定目标这些一类的习惯,只是偶尔会想起应该办这件事了自己就会去做,然而坚持不了多久就放弃了.别人问我我的目标是什么或者我想要什么的时候,我也一概不知道,不知道自己到底在追求什么 ...

  9. 养成一个习惯有多难?不如先从一个小目标开始

    导读:你有什么想要达成的习惯吗?例如坚持一个月读一本书.坚持锻炼维持身材? 达成习惯,需要制定一个明确的可达成的目标,从一个小目标开始,循序渐进.如果你想要达成的习惯是,每天坚持阅读,不断输入新知识. ...

最新文章

  1. android studio 同类,让Android Studio的Project视图和Anroid视图类似
  2. linux 查找 jdk 安装路径
  3. Rails的作者DHH获奖:Winning Google/O'Reilly's Best Hacker of '05
  4. AndroidStudio中使用XML和Java代码混合控制UI界面实现QQ相册照片列表页面
  5. win10 WSL windows subsystem for linux update setup wizard ended prematurely
  6. C语言字符串中删除重复的字符的算法(附完整源码)
  7. java空间租用_java影片租赁平台
  8. asp.net怎么生成json数据_mysql数据库配置文件不知道怎么配置?用这个工具一键生成...
  9. Spring aop优雅实现redis分布式锁 aop应用redis分布式锁
  10. H265编码等级以及图像的基础知识
  11. struts 的action 线性安全问题
  12. eslint解决方案整理
  13. PSO算法及其对函数优化问题的处理+PSO算法改进
  14. 详解Unity中的粒子系统Particle System (七)
  15. VPP DPDK,不是翻墙!!
  16. 选择java版本_新手上路之如何选择Java版本
  17. 基于双参数蜜蜂算法解决车辆路径问题(Matlab代码实现)
  18. 五分钟you-get入门
  19. 数据指标体系之战略指标
  20. “数据产品”是怎样的存在?

热门文章

  1. 通过python+ftps远程备份企业数据
  2. python黑科技库:FuckIt.py,让你代码从此远离bug
  3. Elasticsearch Java API 6.2(java client)
  4. struts.xml配置文件中result的语法
  5. Swing如何正确的处理界面中的线程(EDT)
  6. 转载 什么叫真学习 什么叫假学习
  7. PADS Layout VX.2.3 修改层名
  8. 从实际案例聊聊Java应用的GC优化
  9. 第10课--10_04_LVM之二
  10. 工厂模式理解了没有?