Ajax的封装
- 设计模式: 为了解决特定问题而给出的简洁优化的解决方案
- 懒惰模式: 多种方案选择一种的方式
- 例子: 创建 ajax 对象
- 四种方式
- 封装的时候要判断
- 再找个页面你创建两次的时候
- 懒惰模式, 第一次的时候, 判断到第四个, 从第二次开始, 不再进行判断
封装ajax对象
- 封装一个函数,创建xhr对象
- 不需要参数
- 返回值就是一个可以在浏览器使用的xhr对象
- 封装过程
- 把每一种创建方式写成一个函数
- 一次去调用这个函数
- 如果不报错,表示这个方法可以使用
- 如果a函数可以使用,表示a函数里面的代码在当前浏览器可以正常使用
- 我把cerXhr重新赋值,赋值为0
- 从此以后,当你再调用creXhr的时候,其实就是在调用a函数
- 把四个函数放在一个数组里面
- 准备一个开关
- 判断数组里面是不是有能执行的
- 开始的时候是false
- 一旦有一个可以使用 变量赋值为true
creXhr 创建 ajax 对象
@return { OBJECT } 当前浏览器使用的 ajax 对象
function creXhr() {
var xhr = null;
// 准备一个变量
var flag = false
// 根据各种判断, 来给 xhr 赋值
var arr = [
function () { return new XMLHttpRequest() },
function () { return new ActiveXObject('Microsoft.XMLHTTP') },
function () { return new ActiveXObject('Msxml.XMLHTTP') },
function () { return new ActiveXObject('Msxml2.XMLHTTP') }
]
// arr[i] 是里面的每一个函数
for (let i = 0; i < arr.length; i++) {
try {
xhr = arr[i]()
// 这里的代码可以执行, 表示 arr[i] 函数里面写的代码就是当前浏览器用的
creXhr = arr[i]
flag = true
break
} catch (e) {}
}
// 判断 flag
// 如果式 false, 表示数组里面的每一个都不能用
if (!flag) {
xhr = '您的浏览器不支持 ajax, 请更换浏览器重试'
throw new Error(xhr)
}
// 返回 xhr
return xhr
}
封装ajax操作
- 哪些作为参数使用
- 请求方式
- 请求地址
- 是否异步
- 是否执行JSON.parse()
- dataType:默认是’string’,表示不解析,‘json’
- 传递给后端的数据
- data:‘a=100&b=200’ || { a: 100, b: 200 }
- 确定一下传递参数的方式
- function ajax(){}
- ajax(’./xxx/php’,null,null,‘json’,‘a=100’)
- ajax({type:‘GET’})
- 对象的方式来传递参数
开始封装
- 参数验证:你传递的是不是符合规则
- 1-1url 验证, 必填
- 1-2. type 验证, 可以不传递, 可以是 GET, 可以是 POST, 大小写无所谓,其他的都不行
- 1-3. async 验证, 可以不传递, 可以是 true 可以是 false,
- 1-4.dataType 验证, 可以不传递, 要么是 ‘string’ 要么是 ‘json’
- 1-5. data 验证, 可以不传递, 可以是字符串类型, 可以是 object 类型
- 1-6. success 和 error 验证, 可以不传递, 要么就得是函数
- 设置一套默认值
- 后期的请求发送都是使用默认值发送
- 设置默认值的时候, 把 data 单独操作一下
- 判断如果是一个对象, 我把他还原成 字符串的形式再使用
- 发送请求
- 回调函数
- 目前发送 ajax 只能把结果再控制台打印
- 我们就把想在请求结束后做的事情包装成一个 盒子, 传递给 ajax 里面
- 让他在请求成功的时候, 给我把盒子执行掉
function ajax(options = {}) {
// options = {} 目的: 为了保证你的 options 是一个对象
// 我执行 options.xxx 的时候不会报错
// options.success 和 error 式两个函数数据类型或者没传递
// 1. 参数验证
// 1-1. 验证 url
if (!options.url) {
throw new Error('url 为必填选项')
}
// 1-2. 验证 type
if (!(options.type == undefined || options.type.toUpperCase() === 'GET' || options.type.toUpperCase() === 'POST')) {
throw new Error('目前只接收 GET 或者 POST 请求方式, 请期待更新')
}
// 1-3. 验证 async
if (!(options.async == undefined || typeof options.async === 'boolean')) {
throw new Error('async 需要一个 Boolean 数据类型')
}
// 1-4. 验证 dataType
if (!(options.dataType == undefined || options.dataType === 'string' || options.dataType === 'json')) {
throw new Error('目前只支持 string 和 json 格式解析, 请期待更新')
}
// 1-5. 验证 data
if (!(options.data == undefined || typeof options.data === 'string' || Object.prototype.toString.call(options.data) === '[object Object]')) {
throw new Error('data 参数只支持 string 和 object 数据类型')
}
// 1-6. 验证 success 和 error
if (!(options.success == undefined || typeof options.success === 'function')) {
throw new Error('success 传递一个函数类型')
}
if (!(options.error == undefined || typeof options.error === 'function')) {
throw new Error('error 传递一个函数类型')
}
// 代码来到这里, 说明 options.success 和 error 肯定是一个 undefined 或者 function
// 2. 设置一套默认值
var _default = {
url: options.url,
// 代码能来到这里, 说名 undefined get post
type: options.type || 'GET',
// 代码能来到这里, 说明 undefined true false
// 三元表达式, 如果你式个 布尔值, 那么就用你的, 否则用 true
async: typeof options.async === 'boolean' ? options.async : true,
// 代码能来到这里, 说明 undefined 'string' 'json'
dataType: options.dataType || 'string',
// 代码能来到这里, 说明 undefined '' {}
data: options.data || '',
// 如果你传递了是一个 function, 就用你传递的, 否则我就给一个默认函数
success: options.success || function () {},
error: options.error || function () {}
}
// 到这里, _default.success 和 error 肯定式一个函数
// 2-2. 单独调整一下 data
// 能来到这里, _default.data 只能是 '' {}
if (typeof _default.data === 'object') {
// 准备一个空字符串
var str = ''
for (var key in _default.data) {
str += key + '=' + _default.data[key] + '&'
}
// 拼接完毕以后, 把最后一位去掉, 从新赋值给 _default.data
_default.data = str.slice(0, -1)
}
// 3. 发送请求
var xhr = creXhr()
// 3-1. 请求地址, 如果是 get 请求 url + '?' + data
// 如果式 post 请求 url
// 判断, 如果是 get 请求, 那么我把 _default.url 修改一下
if (_default.type.toUpperCase() === 'GET' && _default.data) {
_default.url += '?' + _default.data
}
xhr.open(_default.type, _default.url, _default.async)
xhr.onreadystatechange = function () {
if (xhr.status >= 200 && xhr.status < 300 && xhr.readyState === 4) {
// 3-3. 判断 dataType 如果式 json 要解析
if (_default.dataType === 'json') {
// 成功, 不需要打印
// 调用 _default.success()
var res = JSON.parse(xhr.responseText)
// 要吗调用的式你传递进来的函数, 要吗调用的式默认函数
// 调用的如果式默认函数, 那么就相当于什么都没执行
// 如果调用的式你传递进来的函数, 那么你在函数里面写什么就执行什么
_default.success(res)
} else if (_default.dataType === 'string') {
_default.success(xhr.responseText)
}
}
if (xhr.readyState === 4 && xhr.status >= 400) {
_default.error(xhr.status)
}
}
// 3-2. 判断是不是 post 请求
if (_default.type.toUpperCase() === 'POST') {
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
}
xhr.send(_default.data)
}