写这篇文章的初衷:写了5年代码,发现每天的工作都是在像拼积木一样,拼凑着一个又一个功能,但是基本的实现原理可能就那几把刷子,想着想着就干脆整理成一个自己风格的公共库,既然说了,那就干呗~
先把最常用的一个方法—ajax入手,发现认真去做一件事情还真的不容易,所以就把这个封装ajax的过程整理成一个博客,供大家参考,小弟也虚心听取各位大佬建议~~~
框架起步
框架的封装是一个开发者综合能力的一个体现,因为框架的封装不仅关系到怎么让使用者更方便的去使用你封装的这个方法,更需要一个开发者从原理上去了解为了实现这种方法所进行的每一步操作,每一个方法的有效性,能不能用更精简的语句实现,能不能用更高效的方法实现,或者是为了追求某方面的性能而牺牲某方面的体验等等…
暂时想不到好的名字,暂时把框架命名为fly.js
框架封装的原则
根据jquery的源码,可见咱们这个框架的封装一般包括两个原则:
-
用匿名函数将脚本包起来
(function(){ })()
-
使用命名空间(多级)
为了防止全局变量命名冲突,咱们使用多级命名空间来避免和项目变量冲突
所以采用F.T,同时因为咱们暂时实现的是工具类库(Util),将来有可能还有UI库,或者其他专门处理String、Object的类库,所以咱们来个F.T.Util- 框架的别名FLY、F、fly等等
- 框架的一些信息
比如框架名、版本号、项目地址[github]、作者信息等等
给大家看一下初始代码长成什么样,写好后呢,将咱们的FLY挂载到windows上
(function(FLY) {
/**
* fly.js
* 版本: 1.0.0
* fly.js尽量覆盖开发过程中的常见的场景,提高开发效率
* 博客: https://blog.youkuaiyun.com/qtfying
* 掘金: https://juejin.im/user/57deadcd0e3dd90069721916
* QQ: 2811132560
* 邮箱: qtfying@gamil.com
*/
F = fly = f = FLY;
F.T = F.T || {};
F.T.Util = F.T.Util || {};
var util = F.T.Util;
})(window.FLY = window.fly || {});
测试工具库是否正常引入
既然框架已经起步,就要先测试一下框架是否能用,咱们先写一个test函数测试一下能不能正常的使用:
util.test = function () {
console.log('引入fly.js框架成功');
};
然后呢,咱们在html界面调用一下,看下能否正常执行即可,当然很完美,咱们接着下一步 ~
new XMLHttpRequest()
属性
一个为向服务器发送请求和解析服务器响应提供了流畅的接口。
ajax是一个老生常谈的问题,但是肯定有一部分人只是知道ajax而不知道XMLHttpRequest,亦或者是在框架横行的世代,为了发一个请求而又不得不把jquery而引入了进来,其实ajax是jquery是为了方便大家使用而封装的一个好用而又方便实用的一个著名的超过
XMLHttpRequest本尊的请求工具,在ES6的Fetch请求之前,发送一个完整的请求一般情况下包括5个步骤:
- 创建XMLHttpRequest对象(浏览器兼容性)
- 注册回调函数
- 创建请求,指定请求类型、地址、异步/同步
- 发送请求
- 异步获取响应数据,并利用js与DOM进行页面局部刷新
实现步骤
//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
ajax.open('get','getStar.php?starName='+name);
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
//步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
if (ajax.readyState == 4 &&ajax.status==200) {
console.log(ajax.responseText); // 输入相应的内容
}
}
readyState
里面这个readyState都有哪些含义呢:
- 0:请求未初始化(还没有调用 open())。
- 1:请求已经建立,但是还没有发送(还没有调用 send())。
- 2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
- 3:请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成。
- 4:响应已完成;您可以获取并使用服务器的响应了。
status
响应的HTTP 状态。
如 200 表示成功,而 404 表示 “Not Found” 错误。当 readyState 小于 3 的时候读取这一属性会导致一个异常。
statusText
HTTP 状态的说明。
当状态为 200 的时候它是 “OK”,当状态为 404 的时候它是 “Not Found”。和 status 属性一样,当 readyState 小于 3 的时候读取这一属性会导致一个异常。
responseText
作为响应主体被返回的文本。
如果 readyState 小于 3,这个属性就是一个空字符串。当 readyState 为 3,这个属性返回目前已经接收的响应部分。如果 readyState 为 4,这个属性保存了完整的响应体。
responseXML
如果响应的内容类型是"text/xml"或"application/xml",这个属性将保存着响应数据的XML DOM文档。
send()
作用:发送请求,参数为发送的请求体,不传请求体的话最好传个null
open()
作用:初始化请求
xhr.open(method,url,async,user,password)
- method 请求方式,如get,post,put等等
- url 请求路径,可以是相对路径也可以是绝对
- async 是否异步请求 传布尔值,默认true
- user 用户名,可选参数,为授权使用;默认参数为空string.
- password 密码,可选参数,为授权使用;默认参数为空string.
老是这样写也不是办法啊,写出精神ICU的节奏啊,这时候,简单而又明了的写法出来了:
$.ajax({
type: "GET",
url: "getUser",
data: {id: val}, // 看后台要什么格式的,是字符串还是对象 JSON.stringify(obj)
success: function(data){},
error: function(){},
});
封装ajax
$.ajax中的一个对象,包含type、url、data、success、error大大的精简了代码的写法,简单明了 ~
咱们自己手动实现一个ajax方法的话,需要考虑哪些方面呢,结合jquery的源码,并且和原生的XMLHttpRequest()方法对比,根据咱们实际开发的经验,一个完整的请求包括:
- json数据,包括url、type、data、succFn、errorFn
- 处理data中的参数,即将data对象拼接到url
- 请求超时的处理
- get方法和post方法
首先咱们先把第2项处理掉,怎么将譬如{name: 'yeyu', age: 18}
转化为?name=yeyu&age=18
这样的字符串呢:
/**
* 将参数转拼接为url链接后的传参
* @returns {{String}}
*/
util.json2url = function(json) {
var arr = [];
for(var name in json) {
arr.push(name + '=' +json[name]);
}
return arr.join('&');
};
接下来我就直接把封装好的ajax方法贴出来,供大家参考:
/**
* 结合jquery,重新封装ajax
* @returns {{responseText}}
*/
util.ajax = function (json) {
var timer = null;
json = json || {};
if (!json.url) {
alert('请求url不存在,请重新检查');
return;
}
json.type = json.type || 'get';
json.time = json.time || 10;
json.data = json.data || {};
var _Ajax = new XMLHttpRequest();
switch (json.type.toLowerCase()) {
case 'get':
_Ajax.open('GET', json.url + '?' + util.json2url(json.data), true);
_Ajax.send();
break;
case 'post':
_Ajax.open('POST', json.url, true);
_Ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
oAjax.send(util.json2url(json.data));
break;
}
_Ajax.onreadystatechange = function() {
if (_Ajax.readyState == 4) {
if (_Ajax.status >= 200 && _Ajax.status < 300 || _Ajax.status == 304) {
clearTimeout(timer);
json.succFn && json.succFn(_Ajax.responseText);
} else {
clearTimeout(timer);
json.errFn && json.errFn(_Ajax.status);
}
}
};
timer = setTimeout(function() {
alert('请求超时,请重新处理 ~ ');
_Ajax.onreadystatechange = null;
}, json.time * 1000);
};
到这里咱们就实现了一个ajax的方法,而不用因为仅仅使用ajax而将jquery引入到项目中
最后呢,再封装两个方法,一个post,一个get,这样基本上就满足了我们项目中常用的请求
/**
* post请求
* @returns {{responseText}}
*/
util.post = function (jsonData) {
ajax({
url: jsonData.url,
data: jsonData.data,
succFn: jsonData.succFn,
errFn: jsonData.errFn,
type: 'post'
});
};
/**
* get请求
* @returns {{responseText}}
*/
util.get = function (jsonData) {
util.ajax({
url: jsonData.url,
data: jsonData.data,
succFn: jsonData.succFn,
errFn: jsonData.errFn,
type: 'get'
});
};
到这里,完整的ajax请求就结束了~~~