小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
一、Ajax 原理
AJAX 即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。
访问网站时,离不开HTTP协议,也离不开请求与响应,
用户端----请求---->服务器端
用户端<----响应----服务器端
问: 你见过哪些 Client(用户端)?
答:Firefox ,chrome,等浏览器
问: Client 只能是浏览器吗?
答: 凡是能发送 HTTP 请求的,都可称为 Client
浏览器中,提供了一个JS对象--XMLHttpRequest
它也可以帮我们发送HTTP请求,并接受Server的响应. 这意味着,我们的浏览器不提交,通过JS也可以请求服务器. Ajax,其实就是通过XHR对象,执行HTTP请求. 所以,学习的关键是---弄清XHR对象的属性和方法.
二、创建XHR对象
- 创建对象
var xhr = new XMLHttpRequest();
- 发送请求
shr.open('请求方式','URL地址',同步:false/异步:true);
- 传入值(使用get方式时填null,post就填需要传入的内容)
xhr.send('值');
- xhr对象的属性:
- readyState:代表请求的状态
- 0:对象已经被创建,但还没有调用open
- 1:已经调用了onpe方法,但尚未发送请求
- 2:请求已经发送出去了 - 3:可以接受部分相应的数据了
- 4:已经接受了所有数据,并且关闭了连接
- responseText:响应的内容
- status:响应状态码,例:200,403,404等等
- statusText:响应状态文字,例:ok,forbidden,not found等等
- 事件(当readyState发生变化是,会触发这个事件)
onreadystatechange=function(){};
- 实例:
新建一个ajax文件夹,ajax文件夹下新建ajax.html和ajax.php
<html>
<head>
<meta charset="UTF-8">
<title>PHP中使用ajax</title>
</head>
<body>
<input type="submit" name="ajax" value="提交" onclick="rep()">
</body>
<script type="text/javascript">
var inp = document.getElementsByTagName('input')[0];
function rep(){
//1.创建对象
var xhr = new XMLHttpRequest();
//2. 发送请求
xhr.open('get','ajax.php',true);
//3. 传的值
xhr.send(null);
//4. 添加判断,设置请求完成时输出请求内容
xhr.onreadystatechange = function (){
if (this.readyState == 4){
alert(this.response)
}
}
}
</script>
</html>
php
<?php
echo 1;
?>
点击提交后:
三、Ajax实例之验证用户名
设置通过判断用户名是否可用确认是否可注册
html页面:
<html>
<head>
<meta charset="UTF-8">
<title>PHP中使用ajax</title>
</head>
<body>
用户名:
<input type="text" name="username" placeholder="请输出用户名">
<span id="rep"></span>
<input type="submit" name="ajax" value="提交" onclick="rep()">
</body>
<script type="text/javascript">
var status = 0;
var inp = document.getElementsByTagName('input')[0];
inp.onblur = function (){
//1.创建对象
var xhr = new XMLHttpRequest();
//2. 发送请求
xhr.open('get','ajax.php?username='+inp.value,true);
//3. 传的值
xhr.send(null);
/* post方式
//2. 发送请求
xhr.open('post','ajax.php',true);
//3. 使用post需要设置请求头
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
//4. 传的值;多参数形式:'username=' + this.value + '&page=' + this.value
var data = 'username=' + this.value;
xhr.send(data);
*/
//4. 获取到span
var span = document.getElementById('rep');
//5. 添加判断,设置请求完成时输出请求内容
xhr.onreadystatechange = function (){
if (this.readyState == 4){
if (this.responseText == 1){
span.innerText = '名称已存在!';
span.style.color = 'red';
status = 0;
}else{
span.innerText = '名称可使用';
span.style.color = 'green';
status = 1;
}
}
}
}
function rep(){
if (status == 1){
alert('注册成功');
}else{
alert('注册失败');
}
}
</script>
</html>
php页面:
<?php
//post方式
//$op = $_POST['username'];
$op = $_GET['username'];
$arr = array('lisi','zhangsan','zhaosi','liuneng');
echo in_array($op,$arr)?1:0;
?>
效果:
四、返回值
一般ajax的返回值只有两种,分别是text和XML两种
- 使用json返回
html:
// 创建xhr对象
var xhr = new XMLHttpRequest();
// 使用get方式提交
xhr.open('get','json返回值.php',true);
// 需要传的参
xhr.send(null);
// 请求完成后输出结果
xhr.onreadystatechange = function (){
if (this.readyState == 4){
// 将PHP返回数据保存起来
var res = this.responseText;
// 将json数据转换为js数组对象
var jsRes = JSON.parse(res);
console.log(jsRes)
console.log(typeof jsRes.name,typeof jsRes.age)
console.log(jsRes.name,jsRes.age)
}
php:
<?php
$arr = array('name'=>'张三','age'=>18);
// 将PHP数组转换为js数组
echo json_encode($arr);
?>
结果:
- 使用XML(使用的较少了,这里省略)
五、同步和异步
同步和异步是什么?
-
- 同时执行:代码一行行执行,上面的没执行完,下面的不许执行
- 异步执行:上下两行代码同时执行,上面一行没执行完时,就开始执行下面的代码
例子:
html代码:
function t1(){
// 创建xhr
var xhr = new XMLHttpRequest();
// true:异步请求,false:同步请求
xhr.open('get','同步和异步.php',true);
// 传参
xhr.send(null);
// 请求完成后输出
xhr.onreadystatechange = function (){
if (this.readyState == 4){
console.log(this.responseText);
}
}
}
function t2(){
console.log(132)
}
t1();
t2();
PHP代码:
<?php
sleep(3);
echo '你好';
效果:
异步时:
同步时:(虽不知为何会输出黄色的警告信息,且不会输出你好,但是效果到了就行)
大概就是你去买东西,付钱的时候发现没带钱,于是你要回家拿钱(别杠我说有手机支付)
同步:排在你后面的人等待你回家拿钱支付完毕后,她、他在付钱
异步:你回家拿钱的同时,你后面的人开始付钱
总之同步就是:你要做什么时,等多久,大家一起等(都是呆比)
异步就是:你要做什么事情时等多久,大家不一起等,大家先做
六、跨域
ajax默认不能跨域,及只能请求同域名之下的内容
通过给PHP添加请求头以达到跨域请求的目的:
Access-Control-Allow-Origin:*//域名,*代表允许所有
七、利用jsonp的方式实现跨域访问
- Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服
务,只要是跨域请求,一律不准;
- Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个
属性的标签都拥有跨域的能力,比如script、img、 iframe);
- 就是在远程服务器上设法动态的把数据装进js格式的文件里,供客户端调用和进一步处理;
- 客户端获取数据后,按照自己的需求进行处理,这种方式看起来像ajax,但是和ajax并没有关
系;
- 为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协
议的一个要点就是允许用户传递一个callback参数给服务 端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
1. 简单模拟下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用jsonp达到跨域请求</title>
</head>
<body>
<script type="text/javascript">
function so(a){
alert(a.name)
}
</script>
<script src="http://localhost:88/PHP的学习/ajax/5.使用jsonp达到跨域请求.php"></script>
</body>
</html>
php:
// 不用加上PHP的文件头
// 伪造一个jsonp
so({'name':'张三'});
效果:
2. 利用jsonp实现获取360搜索信息
360搜索请求:
代码:
function so(){
var search = document.getElementById('search')
var url = 'http://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word,obdata&word='
+search.value;
var sc = document.createElement('script')
sc.src = url;
document.getElementsByTagName('head')[0].appendChild(sc);
}
// suggest_so 360的回调函数
function suggest_so(text){
// 接受参数是个对象,有result属性和值;循环创建
var html ='';
for(var i=0 ;i<text.result.length;i++){
html = html + '<li>'+ text.result[i].word +'</li>';
}
document.getElementsByTagName('ul')[0].innerHTML = html;
}
效果:
八、Ajax 配合 PHP 文件上传
自HTML5出来后,浏览器新增了FormData对象,而且XHR对象也新增了
一些功能, 可以让我们完成ajax上传,且有进度条效果。
html代码:
// style:
#box{
width: 300px;
height: 10px;
border: 1px solid red;
margin: 1px;
}
#box #prog{
height: 10px;
width: 0%;
background-color: blue;
}
// html:
<form action="" method="post" enctype="multipart/form-data" target="frm">
<input type="file" name="pic">
<input type="submit" value="提交">
<p>未上传文件</p>
</form>
<div id="box">
<div id="prog"></div>
<span>0%</span>
</div>
// js
<script type="text/javascript">
// form表单默认一次性只能传大小最多8M的文件
/*
* 如果需要修改,则需要修改xampp的php.ini配置文件下的
* post_max_size=8M
* upload_max_filesize=8M
* 例:post_max_size=800M
* 修改完后需要重起xampp
* */
const fom = document.getElementsByTagName('form')[0];
fom.onsubmit = function (){
// formDate会把表单中的所有数据,整体打包给 this
let data = new FormData(this)
let xhr = new XMLHttpRequest()
let p = document.getElementsByTagName('p')[0]
xhr.onreadystatechange = function(){
p.innerText = '上传中'
if (this.readyState === 4){
p.innerText = '上传成功'
p.style.color = 'green'
}
}
// ajax 的文件上传
xhr.upload.onprogress = function(ev){
/* 返回值:需要实现进度条效果,只需要关注 loaded 和 total 两个参数就行
* isTrusted: true, // ...
* lengthComputable: true, // ...
* loaded: 2130896, // 目前已上传的文件数量
* total: 2130896, // 文件大小
* type: "progress", // ...
*/
console.log(ev)
// 计算上传进度
let jd = 100*ev.loaded/ev.total;
// 因为上传的文件比较小,所以进度条会在一瞬间就满了
// 如果想要进度效果,可将上传限制改大,在上传几十或者几百的文件
document.getElementById('prog').style.width = jd + '%' // 上传进度条
document.getElementsByTagName('span')[0].innerText = Math.ceil(jd) + '%' // 上传百分比
}
xhr.open('post','6.ajax文件上传.php',true)
xhr.send(data)
// 返回 false 保存上传的状态
return false
}
</script>
php:
<?php
// 将上传的文件移动到当前目录
echo move_uploaded_file($_FILES['pic']['tmp_name'],'./'.$_FILES['pic']['name']);
?>
效果:
结果: