Ajax 异步内容
简介
异步操作是JavaScript中最重要的内容之一,通过ajax获取同域网页的内容和通过ajax获取验证结果是项目开发当中常见的操作,本框架也有自己的ajax方法。
axAjax
异步请求是软件开发中使用最频繁的操作方法之一,axAjax不求大而全,只求在开发框架过程中不断完善。
该工具函数有几点需要特别说明下:
- 默认是以application/x-www-form-urlencoded形式发送数据的
- 参数data会自动判断data是否是FormData格式,此类型将不进行数据处理而发送(PHP页面以$_FILES可直接取得文件),如果特别需要请用contentType指明为multipart/form-data
- 如果希望data按json格式发送,请用参数contentType指明为application/json,发送的数据为JSON.stringify(data),在动态页面对json字符串进行解析还原
- 如果data是字符串格式,请严格按照类似name=LiLei&age=16的拼接格式编写
- 该函数返回一个promise对象,可使用then方法
完整写法:axAjax(option, elem,callback).then(resolve,reject)可简写为:axAjax(option),参数说明如下:
- option:必填项,异步参数,格式如{url:''};option的选项如下:
- url:获得异步内容页面
- selector:异步内容中的选择器,可以填"#id"、".className"、"div";如果不填写会将body内容载入(不包括body标签),如果填写只会载入选择器中的内容。
- type:数据请求方式,默认post,可选择get
- async:是否是异步,默认true,可选择false即同步;一般使用true,否则该异步函数失去了意义。
- uploading:异步上传进度回调函数,支持一个参数,该参数为对象,对象属性如下:
- current:已经上传的文件比特值
- total:文件的总比特值
- ratio:已上传和总大小比值,即current / total
- percent:进度百分数,即ratio*100后四舍五入值
- result:带%的总进度字符串,即percent+'%'
- time:完成需要的时间,单位毫秒
- dom:异步操作的节点,如果填写了elem参数,则dom==elem
- downloading:异步下载进度回调函数,支持一个参数,该参数为对象,对象属性如下:
- current:已经下载的文件比特值
- total:文件的总比特值
- ratio:已下载和总大小比值,即current / total
- percent:进度百分数,即ratio*100后四舍五入值
- result:带%的总进度字符串,即percent+'%'
- timeStamp:完成需要的时间,单位毫秒
- dom:异步操作的节点,如果填写了elem参数,则dom==elem
- before:成功获取前的内容,通常是函数function(response){},参数response为一个对象,属性如下:
- content:是加载图形,默认是'<span class="ax-loading"><i></i></span>'
- status:当前状态值,即xhr.status的值
- dom:存放结果的Dom,如果有填写elem参数则为elem,如果没有则为null
- xhr:异步请求的XMLHttpRequest对象
- abort:异步请求的取消方法,在success前可使用该方法中止请求
- opened:创建xhr后,发送请求前执行,属于before的前期阶段,参数同before回调
- success:成功获取后的内容,通常是函数function(response){},参数response为一个对象,属性如下:
- content:获取成功后返回的内容
- status:当前状态值,即xhr.status的值,通常等于200
- dom:存放结果的Dom,如果有填写elem参数则为elem,如果没有则为null
- xhr:异步请求的XMLHttpRequest对象
- abort:中止请求后返回的内容,通常是函数function(dom,xhr){}
- dom:存放结果的Dom,如果有填写elem参数则为elem,如果没有则为null
- xhr:当前XMLHttpRequest实例
- error:获取失败的内容,通常是函数function(response){},参数response为一个对象,属性如下:
- content:获取成功后返回的内容
- status:当前状态值,即xhr.status的值,通常等于404
- dom:存放结果的Dom,如果有填写elem参数则为elem,如果没有则为null
- xhr:异步请求的XMLHttpRequest对象
- data:发送的数据,支持三种数据格式:
- 拼接字符串:类似“name=Lily&age=18&father=Piter”
- json对象:类似{name:'Lily',age:18,fater:'Piter'}
- ForData对象:通过new FormData构建的对象
- delay:异步请求多久后结束,默认60000(毫秒)
- responseType:设置数据类型,默认为空(等同于text),可填json、blob、arraybuffer和document
- contentType:设置发送类型(Content-Type),默认为application/x-www-form-urlencoded,可填application/json、multipart/form-data或text/xml
- catchable:是否允许promise中捕获错误,默认为false也就是不捕获错误以让程序顺畅运行,因为error参数是与reject同时执行的,所以默认屏蔽掉reject
- headers:设置多个请求头,是contentType参数的扩展,是一个对象,格式如下:
- 对象数组设置请求头多对值,比如:{'content-Type','application/x-www-form-urlencoded','Accept':''}
- timeout:超时后的内容,通常是函数
- loading:加载缓冲内容,默认是'<span class="ax-loading"><i></i></span>'
- elem:选填项,存放内容的节点,可以填"#id"、".className"、"div"等原生选择器以及Dom对象。
- callback:选填项,是promise的回调函数,等同于option.before函数。
- then(resolve):成功获取后的内容,相当于option.success,通常是函数function(response){},参数response为一个对象,属性如下:
- content:获取成功后返回的内容
- status:当前状态值,即xhr.status的值
- dom:存放结果的Dom,如果有填写elem参数则为elem,如果没有则为null
- xhr:异步请求的XMLHttpRequest对象
- then(reject):获取失败后的内容(先将catchable设为true),相当于option.error,通常是函数function(response){},参数response为一个对象,属性如下:
- content:获取失败后返回的内容
- status:当前状态值,即xhr.status的值,通常等于404
- dom:存放结果的Dom,如果有填写elem参数则为elem,如果没有则为null
- xhr:异步请求的XMLHttpRequest对象
变量和操作方法
axAjax函数会产生一个外部可用变量和一个外部可用方法:
axAjax().xhr
:对象格式,当前的XMLHttpRequest实例axAjax().abort()
:函数格式,让请求中止
需要注意的是使用abort()方法中止请求之后会停止执行timeout事件。但是不会中止progress、error等事件,也就是说即使abort中止了请求,上传或下载依然在进行,如果需要中止所有事件请使用abort参数进行设置或对xhr变量进行监听。
异步获取整个页面
使用elem参数用来存放异步后的内容。获取内容
-
<a href="###" id="btnPage" class="ax-btn ax-primary ax-sm">获取内容</a> <div id="ajaxPage"></div>
-
document.querySelector('#btnPage').onclick = function () { axAjax({ url: 'ajax/article.html', success: function (content) { //使用setTimeout模拟缓冲效果 setTimeout(function () { document.querySelector('#ajaxPage').innerHTML = '获取成功!打开f12,查看控制台!'; console.log(content) }, 5000); }, }, '#ajaxPage') }
异步获取页面某ID内容
-
<a href="###" id="btnId" class="ax-btn ax-primary ax-sm">获取内容</a> <div id="ajaxId"></div>
-
document.querySelector('#btnId').onclick = function () { axAjax({ url: 'ajax/article.html', //url: 'ajax/article.html#post02', selector:'#post02', success: function (content) { //使用setTimeout模拟缓冲效果 setTimeout(function () { document.querySelector('#ajaxId').innerHTML = content; }, 5000); }, }, '#ajaxId') }
异步获取Json
使用url引用json页面,使用for+in方法拆解json内容并重新组装,使用elem参数用来存放异步后的内容。获取内容
-
<a href="###" id="btnJson" class="ax-btn ax-primary ax-sm">获取内容</a> <div id="ajaxJson"></div>
-
document.querySelector('#btnJson').onclick = function () { axAjax({ url: 'ajax/axui.json', success: function (content) { //重新组装内容 let html = '
- ';
for(let k in content){html+='
- '+k+':'+content[k]+' '; html+='
自定义获取前内容
修改loading参数内容以改变获取前的显示内容,使用elem参数用来存放异步后的内容。获取内容
-
<a href="###" id="btnBefore" class="ax-btn ax-primary ax-sm">获取内容</a> <div id="ajaxBefore"></div>
-
document.querySelector('#btnBefore').onclick = function () { axAjax({ url: 'ajax/axui.json', loading:'加载中,请稍后!', success: function (content) { //使用setTimeout模拟缓冲效果 setTimeout(function () { document.querySelector('#ajaxBefore').innerHTML = '获取成功!'; }, 5000); }, }, '#ajaxBefore') }
获取失败
如果url错误,会触发ajax的error状态,将执行error参数(函数),使用elem参数用来存放异步后的内容。
如果预料到获取失败可使用abort方法提前中止获取,有两种方法可中止请求,请观摩以下示例。
-
<a href="###" id="btnError" class="ax-btn ax-primary ax-sm">获取内容</a> <a href="###" id="btnCancel" class="ax-btn ax-sm">内置方法取消获取</a> <a href="###" id="btnCancel02" class="ax-btn ax-sm">原生方法取消获取</a> <div id="ajaxError"></div>
-
let promise, btnError = document.querySelector('#btnError'), btnCancel = document.querySelector('#btnCancel'), btnCancel02 = document.querySelector('#btnCancel02'), ajaxError = document.querySelector('#ajaxError'), timer; btnError.onclick = function () { promise = axAjax({ url: 'ajax/xxxxx', abort: (dom) => { dom.innerHTML = '内置abort方法中止获取!'; }, error: function (content, status, dom) { //使用setTimeout模拟缓冲效果 timer = setTimeout(function () { dom.innerHTML = '获取失败!'; }, 5000); }, }, ajaxError); } btnCancel.onclick = function () { if (promise) { //取消定时 timer ? clearTimeout(timer) : null; //放弃获取(内置abort方法) promise.abort(); } } btnCancel02.onclick = function () { if (promise) { //取消定时 timer ? clearTimeout(timer) : null; //获取xhr变量 let xhr = promise.xhr; //放弃获取(原生abort方法) xhr.abort(); ajaxError.innerHTML = '原生abort方法中止获取!' } }
异步检索
构造data对象,通过GET方法(使用POST也可以)传递至后台进行校验。
-
<form action="ajax/user.php" id="ajaxSearch"> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label">学生编号:</div> <div class="ax-form-con"> <div class="ax-form-input"><input name="number" placeholder="输入编号" type="text"></div> </div> <span class="ax-form-txt">填“01~07”</span> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label"></div> <div class="ax-flex-block"> <div class="ax-form-input"><button type="button" class="ax-btn ax-primary ax-full">提交</button></div> </div> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label"></div> <div class="ax-flex-block"> <div class="result"></div> </div> </div> </div> </form>
-
document.querySelector('#ajaxSearch button').onclick = function () { //获得要传递的值 let form = document.querySelector('#ajaxSearch'), formData = {}; form.querySelectorAll('[name]').forEach(function (item) { formData[item.getAttribute('name')] = item.value.trim(); }); axAjax({ url: 'ajax/search.php', data: formData, type: 'post',//默认是post,可选择get success: function (content, status, dom) { //使用setTimeout模拟缓冲效果 setTimeout(function () { dom.innerHTML = content; }, 1000); }, }, '#ajaxSearch .result') }
-
<?php header("Content-Type:text/plain;charset=utf-8"); //定义student变量,是被检索内容 $student = array ( array("name" => "刘伟","number" => "01","grade" => "初一"), array("name" => "张继红","number" => "02","grade" => "初三"), array("name" => "王萌","number" => "03","grade" => "初一"), array("name" => "魏训天","number" => "04","grade" => "高二"), array("name" => "王川","number" => "05","grade" => "高一"), array("name" => "欧阳泽","number" => "06","grade" => "高三"), array("name" => "唐文明","number" => "07","grade" => "初二"), ); //定义number变量 if($_SERVER["REQUEST_METHOD"] =="GET") { $number = $_GET["number"]; } elseif($_SERVER["REQUEST_METHOD"] == "POST") { $number = $_POST["number"]; } //判断出结果 if(!isset($number) || empty($number)) { echo "未填学生编号!"; return; } $result = "没有这个人!"; forEach($student as $value) { if($value["number"] == $number) { $result = "找到了!编号:".$value["number"].",姓名:".$value["name"].",年级:".$value["grade"]; break; } } echo $result; ?>
异步上传
构造data对象,通过POST方法传递至后台进行校验上传。
-
<form id="ajaxPost"> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label">学生姓名:</div> <div class="ax-form-con"> <div class="ax-form-input"><input name="name" placeholder="输入姓名" type="text"></div> </div> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label">学生编号:</div> <div class="ax-form-con"> <div class="ax-form-input"><input name="number" placeholder="输入编号" type="text"></div> </div> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label">学生年级:</div> <div class="ax-form-con"> <div class="ax-form-input"><input name="grade" placeholder="输入年级" type="text"></div> </div> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label"></div> <div class="ax-flex-block"> <div class="ax-form-input"><button type="button" class="ax-btn ax-primary ax-full">提交</button></div> </div> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label"></div> <div class="ax-flex-block"> <div class="result"></div> </div> </div> </div> </form>
-
document.querySelector('#ajaxPost button').onclick = function () { //获得要传递的值 let form = document.querySelector('#ajaxPost'), formData = {}; form.querySelectorAll('[name]').forEach(function (item) { formData[item.getAttribute('name')] = item.value.trim(); }); axAjax({ url: 'ajax/post.php', data: formData, type: 'post', success: function (content, status, dom) { //使用setTimeout模拟缓冲效果 setTimeout(function () { dom.innerHTML = content; }, 1000); }, }, '#ajaxPost .result') }
-
<?php header("Content-Type:text/plain;charset=utf-8"); if(!isset($_POST["number"]) || empty($_POST["number"]) || !isset($_POST["name"]) || empty($_POST["name"]) || !isset($_POST["grade"]) || empty($_POST["grade"])) { sleep(2); echo "信息不完整,请重填!"; return; } echo "恭喜,保存成功!编号:".$_POST["number"].",姓名:".$_POST["name"].",年级:".$_POST["grade"]; ?>
异步登录
构造data对象,通过POST方法传递至后台对已有账户进行校验。
-
<form id="ajaxLogin"> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label">账号:</div> <div class="ax-form-con"> <div class="ax-form-input"><input name="name" placeholder="输入账户" type="text"></div> </div> <span class="ax-form-txt">填“李雷”或“韩梅梅”</span> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label">密码:</div> <div class="ax-form-con"> <div class="ax-form-input"><input name="pass" placeholder="输入密码" type="text"></div> </div> <span class="ax-form-txt">填“123456”</span> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label"></div> <div class="ax-flex-block"> <div class="ax-form-input"><button type="button" class="ax-btn ax-primary ax-full">提交</button></div> </div> </div> </div> <div class="ax-break-md"></div> <div class="ax-form-group"> <div class="ax-flex-row"> <div class="ax-form-label"></div> <div class="ax-flex-block"> <div class="result"></div> </div> </div> </div> </form>
-
document.querySelector('#ajaxLogin button').onclick = function () { //获得要传递的值 let form = document.querySelector('#ajaxLogin'), formData = {}; form.querySelectorAll('[name]').forEach(function (item) { formData[item.getAttribute('name')] = item.value.trim(); }); axAjax({ url: 'ajax/login.php', data: formData, type: 'post', success: function (content, status, dom) { //使用setTimeout模拟缓冲效果 setTimeout(function () { dom.innerHTML = content; }, 1000); }, }, '#ajaxLogin .result') }
-
<?php header("Content-Type:text/plain;charset=utf-8"); //定义user变量,是被检索内容 $user = array ( array("name" => "李雷","pass" => "123456"), array("name" => "韩梅梅","pass" => "123456"), ); //判断出结果 if(!isset($_POST["name"]) || empty($_POST["name"]) || !isset($_POST["pass"]) || empty($_POST["pass"])) { echo "信息不完整,请重填!"; return; } $result = "登录失败,没有此账户!"; forEach($user as $value) { if(($value["name"] !== $_POST["name"]) || ($value["pass"] !== $_POST["pass"])){ $result = "登录失败!账户或密码错误"; }else if(($value["name"] == $_POST["name"]) & ($value["pass"] == $_POST["pass"]) ) { $result = "登录成功!账户:".$_POST["name"].",密码:".$_POST["pass"]; break; } } echo $result; ?>
then回调
axAjax返回的是一个Promise
,所以可以使用axAjax({option},elem,callback).then(resolve,reject)
链式异步操作。如果出现二维以上的异步回调,那么应该使用then方法。
需要注意的是,callback相当于option.before
,resolve相当于option.success
,reject相当于option.error
;then方法和option里的函数是会同时执行的,可通过option.before:false,option.success:false,option.error:false来禁用三个函数。
option.before、option.success和option.error三个函数是有默认函数片段的,即如果填了elem,三个函数会对elem进行节点操作,如果elem未填或为空,等于不执行该三个函数的默认函数片段。代码可写作:axAjax({option},'',callback).then(resolve,reject)
。
使用selector参数选择异步页面的id,使用elem参数用来存放异步后的内容。获取内容
-
<a href="###" id="thenBtn" class="ax-btn ax-primary ax-sm">获取内容</a> <div id="thenId"></div>
-
let thenBtn = document.querySelector('#thenBtn'), thenBox = document.querySelector('#thenId'); thenBtn.onclick = function () { //此时的axAjax会返回第一个的Promise axAjax({ url: 'ajax/article.html', selector: '#post02', }, '', () => { thenBox.innerHTML = '正在加载中...'; }).then((data) => { setTimeout(function () { thenBox.innerHTML = data.content; }, 1000); //此时的axAjax会返回第二个的Promise return axAjax({ url: 'ajax/article.html', }); }).then((data) => { //content是一个数组['内容','状态','节点'] setTimeout(function () { thenBox.innerHTML = data.content; }, 2000); }); }
async/await
axAjax返回的是一个Promise
,所以自然可以使用async/await方法,因为是同步代码的写法,所以在ajax获得数据后不需要在success中写上所有代码。获取内容
-
<a href="###" id="awaitBtn" class="ax-btn ax-primary ax-sm">获取内容</a> <div id="awaitBox"></div>
-
let awaitBtn = document.querySelector('#awaitBtn'), awaitBox = document.querySelector('#awaitBox'), asyncData = '', asyncFun = async () => { console.log('2.同步代码,被阻塞前'); await awaitFun(); console.log('5.异步代码,被阻塞后'); //获得数据后不需要在success里用了,可放到await之后 console.log(asyncData); console.log('总结,代码看上去是按顺序执行的,先有4再有5'); }, awaitFun = () => { return axAjax({ url: 'ajax/article.html', selector: '#post02', success: (content) => { awaitBox.innerHTML = content; asyncData = content; console.log('4.异步代码,完成数据获取'); } }, awaitBox); }; awaitBtn.onclick = function () { console.log('1.同步代码,未被阻塞'); asyncFun(); console.log('3.同步代码,未被阻塞'); }
axAjaxSubmit函数
对axAjax函数进行二次封装形成了更加实用的axAjaxSubmit函数。
完整写法:axAjaxSubmit(url, outer, target,options),可简写为:axAjaxSubmit(url, outer, target)。
具体参数说明如下:
- url:必填项,表单异步提交地址。
- outer:必填项,form节点,可以填"#id"、".className"、"div"等原生选择器以及Dom对象。
- target:必填项,提交表单的按钮节点,可以填"#id"、".className"、"div"等原生选择器以及Dom对象。
- options:选填项,系列参数,详细如下:
- type:选填项,表单提交方式,默认post可选择get。
- success:必填项,提交成功后的回调函数,支持参数reponse,即返回axAjax值。
- loading:选填项,loading元素显示位置,默认button在按钮上显示,可选择form在表单上显示。
- delay:选填项,延缓显示结果的时间,默认1000毫秒。
- before:选填项,成功前的回调函数,支持参数reponse,即返回axAjax值。
- error:选填项,报错回调函数,支持参数reponse,即返回axAjax值。
- opened:选填项,创建请求后的回调函数,支持参数reponse,即返回axAjax值。
- options:选填项,其他参数,已有的参数如下:
- formClass:提交中的表单样式,默认ax-form-submitting。
- buttonClass:提交中的按钮样式,默认ax-button-submitting。
- buttonText:按钮在表单提交时的文本,默认是:正在提交。
- overlayClass:表单遮罩层的样式,默认是ax-form-overlay
- overlayShowClass:表单遮罩层显示的样式,默认是ax-show
- successText:提交成功后message显示的文字,默认是:恭喜!提交成功!
- errorText:提交失败后message显示的文字,默认是:对不起,提交失败!