练习: 学习XMLHttpRequest (即XHR )相关知识,开发一个简单的 ajax 插件,用于异步获取服务端数据。
原书提供的参考代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
const ajax = function (options = {}) { options.type = (options.type || 'GET').toUpperCase(); let data = []; for (let i in options.data) { data.push(encodeURIComponent(i) + '=' + encodeURIComponent(options.data[i])); } data = data.join('&'); const xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { const status = xhr.status; if (status >= 200 && status < 300) { options.success && options.success(JSON.parse(xhr.responseText), xhr.responseXML); } else { options.error && options.error(status); } } }; if (options.type === 'GET') { xhr.open('GET', options.url + '?' + data, true); xhr.send(null); } else if (options.type === 'POST') { xhr.open('POST', options.url, true); xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded'); xhr.send(data); } };
此插件的要求,隐藏在参考代码中,试解析如下:
将ajax功能封装为一个类,此类
1, 接受一个可选的options对象作为参数,其默认值为{}
2, 此Options对象有
type(值为get/post,表明向服务器提出何种请求)、
data(向服务器发出的查询字符串)、
success(成功后的回调函数)、
error(失败回调函数)
url
3, 接收到options参数后,对内部数据进行初始化,
4. 如未提供options参数,则需设置各项数据的默认值
5. 默认提交请求类型为get,
6. 根据提交请求类型,分别进行get或post请求
小结:
1 实现此类后,可给构造器传入一个options对象,根据options中type自动进行get/post请求
例:new Ajax(options)
2 实例此类后,可在实例上调用get方法/post方法,并传递url,data参数,直接进行get/post请求
例:const myAjax=new Ajax();
myAjax.get(url);
myAjax.post(url,data)
解答:(先贴上代码,晚上上注释及测试用的php文件)已测试成功,
简要说明:封闭为了一个 ajax对象,生成实例后,无论是通过实例调用 get / post方法并传入url/data,还是直接给实例传入一个数据 对象字面量,均可成功从服务器获取 数据 !
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>XHR</title> </head> <body> <p>Fill in the form below:</p> <form id="user-info"> <label for="user-name">Name:</label><input type="text" id="user-name" name="user-name" /><br /> <label for="user-email">Email:</label><input type="text" id="user-email" name="user-email" /><br /> <input type="button" value="Submit" onclick="submitData()" /> </form> <script>
//声明类,调用initialize初始化类实例 function ajax() { this.initialize.apply(this, arguments); } ajax.prototype = {
//初始化 initialize(options) { this.setOptions(options); //this.data = this.setData(this.options.data); this.data = this.options.data; this.type = this.options.type; this.url = this.options.url; this.success = this.options.success; this.error = this.options.error; this.xhr = this.createXHR(); this.start(); }, setOptions(options) { this.options = { type: 'GET', data: '', success: function (mes) {alert(mes) }, error: function (mes) {alert(mes) }, url: '', };
//此处可使用es6对象新的Object.assign
方法
//Object.assign(this.options, options); for (var p in options) this.options[p] = options[p]; }, setData(data) { let localdata = []; for (let i in data) { localdata.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i])); } localdata = localdata.join('&'); return localdata; }, createXHR() { const _this = this; const xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { const status = xhr.status; if (status >= 200 && status < 300) { _this.success && _this.success(xhr.responseText); } else { _this.error && _this.error(status); } } }; return xhr; }, get(url) { this.xhr.open('get', url + '?' + this.data, true); this.xhr.send(null); }, post(url,mes) { this.xhr.open('post', url, true);
//注释掉此行代码,是因为使用了FormData来序列化Data,xhr对象能识别传入的数据类型是FormData实例,并配置适当的头部信息。 //this.xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); this.xhr.send(mes); }, start() { var _this = _this; switch (this.type.toUpperCase()) { case 'GET': this.get(this.url); break; case 'POST': this.post(this.url,this.data); break; } } } function submitData() { var form = document.getElementById('user-info'); var data = new FormData(form); objs = { type: 'post', url: 'postexample.php', data: data }; new ajax(objs); } </script> </body> </html>