ajax 简介
业务:
做一个在线投票,给歌手投票。
要求:无刷新,并且不允许使用XMLHttpRequest对象.
分析:在XHR对象,没有流行之前,已经有了“无刷新”这种效果的方法.
从http角度看,可以利用204 No content 状态码的特性
可以使用
iframe
利用图片加载的特性
可以使用
script
无刷新只是表面现象,本质上,是需要发送一个请求,把数据送到后台.
业务需求:
AJAX注册,提交表单,要求页面无刷新.
利用iframe
特性
iframe
嵌入在当前页面。
post提交到当前页面的iframe
中,达到ajax效果
。
总结:
在不使用XMLHttpRequest
对象的情况下,依然可以用js来实现对后台服务器的请求,同时不带来页面刷新或者跳转。
所谓AJAX:
即是指:页面不刷新的情况下,利用XMLHttpRequest
对象发送HTTP请求.或者JavaScript的网络化.
AJAX文件上传实现原理(HTTP协议+JS引擎)的角度:
分析:从HTTP协议的角度来看,则要把文件的内容发送到服务器.如果可以,说明XMLHttpRequest对象在POST数据时,把文件的内容也发送到服务器,---> XHR对象获取了你要上传的文件的内容. ---> JavaScript读取了本地的文件内容. ---> 处于安全原因,JavaScript是不能够读取到本地文件内容.
因此:AJAX原理上是无法实现的.
利用伪AJAX方式来实现.
iframe
来实现.用flash实现。如:
swfuploaded
插件HTML5实现。(HTML5增加了文件读取API)
AJAX
核心:XMLHttpRequest
对象.
XML对象一个专门的HTTP请求的工具.
如何使用XMLHttpRequrest
对象做AJAX请求?
分析:
如何实例化该对象.
如何请求后台资源.
请求结果如何得到(双向通信).
创建XML对象.
new XMLHttpRequest();
如何通过XHR发送请求?
分析HTTP协议,要请求需要明确因素?
根据请求行:
-
用什么方法来请求.
GET,POST,PUT,DELETE,HEAD
请求那个资源(URL)
-
同步方式
同步,异步
获取返回信息
XHR对象本身有一些属性,responseText
,表示返回值.
xhr.responseText
使用异步,如何知道请求完成.
XHR对象在请求与响应的过程中,状态会不断变化(0-4)xhr.readyState
,逐步变化. 可以绑定一个函数,监听状态变化,只要状态发生变化,就触发函数xhr.onreadystatechange
返回值类型
不考虑HTML5最新的标准,返回值:普通文本
/xml文档
.二种返回形式
XML文档
function createXHR() {
var xhr = null;
if ( window.ActiveXObject ) {
xhr = new window.ActiveXObject();
} else if ( XMLHttpRequest ) {
xhr = new XMLHttpRequest('Microsoft.XMLHTTP');
}
return xhr;
}
// xml
function test1() {
var xhr = createXHR();
xhr.open('GET', './returntype.php', true);
xhr.onreadystatechange = function () {
if ( this.readyState == 4 ) {
var xmldom = this.responseXML;
console.log( xmldom );
}
}
xhr.send(null);
}
普通文本
普通文本变通形式:
后台返回大段的html代码,直接innerHTML到前台页面.
json格式的普通文本.
返回简短的标志字符串 如: 0, 1, ok.
function createXHR() {
var xhr = null;
if ( window.ActiveXObject ) {
xhr = new window.ActiveXObject();
} else if ( XMLHttpRequest ) {
xhr = new XMLHttpRequest('Microsoft.XMLHTTP');
}
return xhr;
}
// 返回普通文本的html代码字符串
function test2() {
var xhr = createXHR();
xhr.open('GET', './returnhtml.php', true);
xhr.onreadystatechange = function () {
if ( this.readyState == 4 ) {
console.log( this.responseText );
}
}
xhr.send(null);
}
// json格式字符串对象
function test3() {
var xhr = createXHR();
xhr.open('GET', './returnjson.php', true);
xhr.onreadystatechange = function () {
if ( this.readyState == 4 ) {
console.log( this.responseText );
}
}
xhr.send(null);
}
jsonp格式
jsonp是跨域解决的一种方式.
异步原理
readyState
状态值:
通过插队机制
,把回调函数插入到当前已经执行代码的前方。
HTML5与AJAX
iframe
扑捉表单提交动作(onsubmit)
创建一个iframe
把表单的target修改 指向 该 iframe
销毁iframe
$('form').submit(function () {
var upName = 'up' + Math.random();
$('
$error = $_FILES['pic']['error'] == 0 ? 'success' : 'fail';
sleep(2);
if ( $error == 0 ) {
echo '';
} else {
echo '上传失败';
}
FormData
进度条: 总大小, 已上传大小
解决:在HTML5中,有一个"上传过程"的事件(onprogress),事件中,可以读取到当前两个信息.
思路:在上传过程中,不断触发函数,读取(已上传/总大小),更新页面数据。
FormData使用注意
每个表单域必须有name属性
不能设置
setRequestHeaer
头特殊符号无须编码
在form标签里无须设置
enctype='multipart/form-data'
属性(即使有上传文件域也不需要设置)
(无刷新上传附件,FormData可以收集上的文件域信息)
AJAX对象-> upload -> onprogress
AJAX对象有成员属性upload
,是一个对象,该对象有一个onprogress
属性,该属性是一个时间,该事件每间隔0.1秒执行一次,执行过程中会知道当前的附件上传情况。(例如:文件上传的总大小,目前已经上传大小等信息)
/**
* file文件上传
*/
function selfile() {
// 创建FromData对象
var fd = new FormData();
// 获取文件对象
var pic = document.getElementsByTagName('input')[0].files[0];
// 把获取的文件对象追加到表单数据中.
fd.append('pic', pic);
// fd.pic = pic;
// AJAX
var xhr = new XMLHttpRequest();
xhr.open('POST', 'upfile.php', true);
xhr.onreadystatechange = function () {
if ( xhr.readyState == 4 ) {
document.getElementById("debug").innerHTML = xhr.responseText;
}
}
xhr.upload.onprogress = function ( ev ) {
// 长度是否可以计算. (区分:分块上传)
if ( ev.lengthComputable ) {
// 当前已经上传多少/总共多少
var percent = 100 * ev.loaded / ev.total;
document.getElementById('debug').innerHTML = '已经上传:' + percent.toFixed(2);
}
}
xhr.send(fd);
}
大文件切割上传
while循环实现文件上传
/**
* 使用的API
* file --> Blob
* Blob有slice, 可以截取二进制对象的一部分.
*/
/**
* 思路:
* 截取10M,上传
* 判断文件是否截取完毕
*
* while( 存在数据 ) { // 截取, 上传 }
*/
/**
* 上传文件
*/
function sendFile() {
const LENGTH = 10 * 1024 * 1024; // 一次性截取长度
var start = 0; // 从哪里开始截取
var end = start + LENGTH // 到哪边截至
var blob = new Blob();
var fd = null;
// XHR对象
var xhr = null;
// 获取总的文件大小
var pic = document.getElementById("pic").files[0];
var totalSize = pic.size;
var percent = 0;
while ( start < totalSize ) {
// 截取文件
blob = pic.slice(start, end);
fd = new FormData();
// fd.append('part', blob);
fd.part = blob;
// xml对象
xhr = new XMLHttpRequest();
xhr.open('POST', 'sliceup.php', true);
xhr.upload.onprogress = function ( ev ) {
}
// 发送请求
xhr.send(fd);
start = end;
end = start + LENGTH;
percent += 100 * end / totalSize;
if ( percent > 100 ) {
percent = 100;
}
document.getElementById("msg").style.width = percent + '%';
}
}
定时器实现切割上传