Ajax这一篇足矣

22 篇文章 3 订阅
12 篇文章 0 订阅

Ⅰ- 壹 - 什么是Ajax

  • Ajax = 异步 JavaScriptXML
  • Ajax 不是新的编程语言,而是一种使用现有标准的新方法。
  • 通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  • Ajax技术核心是XMLHttpRequest对象(简称XHR)XHR对象可以直接实例化XMLHttpRequest即可。

一 存在以下缺点:

  • 受同源策略的限制,不能发送跨域请求;

  • 不能发送二进制文件(如图片、视频、音频等),只能发送纯文本数据;

  • 在发送和获取数据的过程中,无法实时获取进度信息,只能判断是否完成;

  • 无法进行操作的后退,即不支持浏览器的页面后退。

  • 对搜索引擎的支持比较弱。

  • 可能会影响程序中的异常处理机制。

  • 安全问题,对一些网站攻击,如csrf、xxs、sql注入等不能很好地防御。

二 Ajax优点:

  • 可以发送跨域请求,在服务端允许的情况下;
  • 支持发送和接收二进制数据;
  • 新增formData对象,支持发送表单数据;
  • 发送和获取数据时,可以获取进度信息;
  • 可以设置请求的超时时间;
  • 页面无刷新,在页面内与服务器通信,减少用户等待时间,增强了用户体验。
  • 使用异步方式与服务器通信,响应速度更快。
  • 可以把一些原本服务器的工作转接到客户端,利用客户端闲置的能力来处理,减轻了服务器和带宽的负担,节约空间和宽带租用成本。
  • 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

三 创建Ajax四步

我们与服务器通信的API就是XMLHttpRequest。
那么我们都需要那些步骤来通信呢,简单理解一共只有4步。

  1. 新建XMLHttpRequest对象
    var request=new XMLHttpRequest();
    IE 7以下 var request=new ActiveXObject(“Microsoft.XMLHTTP”);

  2. 打开要发送的地址通道。
    request.open(“GET”,地址,同步/异步);

  3. 给XMLHttpRequest对象增加侦听器,用来侦听各种情况,包括各种链接状态
    request.addEventListener(“load”,侦听函数)发送数据给打开的地址,

  4. 如果没有要发送的内容直接send()
    request.send();

Ⅱ - 贰 - Ajax的方法

一 xhr.open()

通过XMLHttpRequest ,你可以很容易的取回一个URL上的资源数据. 尽管名字里有XML, 但 XMLHttpRequest 可以取回所有类型的数据资源,并不局限于XML。 而且除了HTTP ,它还支持file 和 ftp 协议.
因此不要局限于网络通信,他同样也可以做当前服务中的文件调用

xhr.Open()参数有:

xhr.open(“Method ”,“URL”,async,“user”,“password”)

参数作用
method发送请求的方式,可选的参数有:GET 、POST 、PUT 、DELETE
URL要发送的URL路径,可以使用绝对路径和相对路径。也可以用来请求本地文件标注a
async请求是否要被异步处理。也可以不写,默认为true。标注b
user访问地址的用户名,可选参数吗,默认参数为空string.
password访问地址的密码,可选参数吗,默认参数为空string.

标注a:

url地址是一个比较强大的内容,如果给服务器传参不需要加密的话,可以通过url来进行传参,通常传参的方法是
http://地址:端口/文件名?参数1=值1&参数2=值2;也可以用来请求本地文件

标注b:

  • true,脚本处理会在send()发送之后继续处理,即异步处理。

  • false,在继续脚本处理之前,脚本会等待某个响应,即同步处理。

小结:

1、URL参数中:

GET是带参数、POST不带参数,如果希望每次请求都是最新的就需要加时间戳

URL地址中通qza 过目录方式带入请求的类型

async 默认是true,异步。如果设置false,是同步,不需要事件侦听

user password 访问地址的用户名密码

二 xhr.send()

发送请求。如果该请求是异步模式(默认),该方法会立刻返回。相反,如果请求是同步模式,则直到请求的响应完全接受以后,该方法才会返回。
注意:所有相关的事件绑定必须在调用 send() 方法之前进行。

xhr.send(ArrayBuffer data);类型化数组
xhr.send(Blob data);二进制大对象,是一个可以存储二进制文件的容器。
xhr.send(Document data); 文档对象
xhr.send(DOMString? data); 文本数据
xhr.send(FormData data); 数据对象,可以直接封装内容

var form=document.querySelector("form");
form.addEventListener("submit",submitHandler);
function submitHandler(e){
    e.preventDefault();
    //新建FormData对象,将form作为参数传进去
    let fd=new FormData(form);
    let xhr=new XMLHttpRequest();
    xhr.addEventListener("load",loadHandler);
    xhr.open("POST","http://127.0.0.1:4006");
    //可以直接发送给服务端,但是要注意,服务端需要对FormData做处理才可以使用
    xhr.send(fd);
}
function loadHandler(e){
    console.log(this.response);
}

(1) FormData()

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.

  1. 可以通过构造函数创建添加
var formData = new FormData();
formData.append("username", "EricXie");
formData.append("age", "30");
formData.append("sex", "men");
xhr.send(formData);
//使用 for of 来遍历
for(let value of formData){
    console.log(value);
}
  1. 可以获取表单中的数据进行添加
//html部分
<form>
        <input type="text" name="user">
        <input type="text" name="password">
        <button type="submit">提交</button>
 </form> 


 <script>
var form=document.querySelector("form");
         form.addEventListener("submit",submitHandler);
         
         function submitHandler(e){
             e.preventDefault();
             var xhr=new XMLHttpRequest();
             xhr.addEventListener("load",loadHandler);
             xhr.open("POST","http://localhost:4006");
             xhr.send(new FormData(form));
         }

         function loadHandler(e){

         }
 </script>

小结:

  • 如果是POST请求的话,传参则应该这么写xhr.send("name=niji");或者xhr.send('{"user":"xietian","age":30}');

三 HTTP 头部(响应头/请求头)

HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST)。如有必
要,客户程序还可以选择发送其他的请求头。大多数请求头并不是必需的,但Content-Length除外。 对于POST请求来说Content-Length必须出现。请通过百度等搜索引擎搜索该内容学习。这部分内容在以后实际应用中有很多是需要使用的。

  • GET方式允许发送自定义消息头,POST不允许、 发送自定义消息头时,必须在服务端设置响应头跨域同意Access-Control-Allow-Headers:"*"

  • 请求消息,必须在open( )后,send( )前写入如果ajax与php通信使用POST方法时,必须这样写入消息头,PHP才可以解析POST数据

方法简介
xhr.getResponseHeader()获取头部指定的属性值
xhr.etAllResponseHeaders()获取所有头部属性
xhr.setRequestHeader()设置头部属性,必须在open以后,send以前写入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZO2S8hVu-1596878281104)(C:\Users\幻影旅团\AppData\Roaming\Typora\typora-user-images\image-20200807202900769.png)]

    var xhr = new XMLHttpRequest();
    xhr.addEventListener("load", loadHandler);
    xhr.open("GET", "http://10.9.65.239:4006?user=nicai&age=30");
    // 这个请求头是让PHP可以解析当前的POST数据
    xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
    //    GET方式允许发送自定义消息头,POST不允许
    // 发送自定义消息头时,必须在服务端设置响应头跨域同意Access-Control-Allow-Headers:"*"
    // xhr.setRequestHeader("abc","3");
    xhr.send();

    function loadHandler(e) {
      // console.log(xhr.getAllResponseHeaders());//获取所有响应头
      // console.log(xhr.getResponseHeader("content-type"));//获取指定的响应头
    }

(1) 请求头信息

请求头简述
Accept客户端支持的数据类型
Accept-Charset客户端采用的编码
Accept-Encoding客户端支持的数据压缩格式
Accept-Language客户端的语言环境
Cookie客服端的cookie
Host请求的服务器地址
Connection客户端与服务连接类型
If-Modified-Since上一次请求资源的缓存时间,与Last-Modified对应
If-None-Match客户段缓存数据的唯一标识,与Etag对应
Referer发起请求的源地址。

(2) 响应头信息

响应头简述
content-encoding响应数据的压缩格式。
content-length响应数据的长度。
content-language语言环境。
content-type响应数据的类型。

四 GET和POST的区别

  1. GET是从服务器上获取数据,POST是向服务器传送数据。
  2. GET把参数包含在URL中,POST通过request body传递参数。
  3. 对于GET方式,服务器端用Request.QueryString获取变量的值,对于POST方式,服务器端用Request.Form获取提交的数据。
  4. GET传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。(这里有看到其他文章介绍GET和POST的传送数据大小跟各个浏览器、操作系统以及服务器的限制有关)
  5. GET安全性非常低,POST安全性较高。
  6. GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  7. GET请求只能进行url编码,而POST支持多种编码方式。

五 创建Ajax、 node开启服务

(1) node开启服务 ajax.js
var http=require("http");
var querystring=require("querystring");
var server=http.createServer(function(req,res){
   
    // 获取请求头消息
    // console.log(req.headers.names);
    var data="";
    // POST方式获取客户端发来的消息,转换为字符串就可以得到
    req.on("data",function(_data){
        data+=_data;
    });
    req.on("end",function(){
        if(req.url.indexOf("favicon.ico")>-1) return;
         if(data.trim().length===0) data=req.url.split("?")[1];   
        else{
            try{
                data=JSON.parse(data);
            }catch(error){

            }
        }
        if(typeof data==="string"){
            try{
                data=querystring.parse(data);
            }catch(error){
                res.end("错误的消息");
                return;
            }
        }
        if(!data){
            res.end("错误的消息");
            return;
        }
    //    设置响应头
        res.writeHead(200,{
            "content-type":"text/html;charset=utf-8",//解决中文乱码问题
            "Access-Control-Allow-Origin":"*",//地址跨域
            "Access-Control-Allow-Headers":"*"//请求头跨域
        })
        res.write((data.user? data.user : "你没有user")+"欢迎光临");
        res.end();
    })
});
// 创建好的服务开启侦听,第一个参数是网络的端口号,第二个参数是网络的ip,第三个参数是开启后的回调函数
server.listen(4006,"localhost",function(){
    console.log("服务已开启");
})
(2) 创建Ajax ajax.html

创建GET请求方式

<script>
 		var xhr=new XMLHttpRequest();//实例化Ajax
        xhr.addEventListener("load",loadHandler);//绑定加载事件
        xhr.open("GET","http://127.0.0.1:4006?user=WWW&age=30")//打开要发送的地址通道  GET请求方式
        xhr.send();//请求结束
        //加载事件函数
        function loadHandler(e){
        //接收服务器响应的数据
            console.log(xhr.response);
        } 

</script>

创建POST请求方式

<script>

        var xhr
        try{
            xhr=new XMLHttpRequest();
        }catch(error){
            xhr=new ActiveXObject("Microsoft.XMLHTTP");//IE7
        }
        xhr.addEventListener("load",loadHandler);
        xhr.open("POST","http://localhost:4006");
        xhr.send('{"user":"WWW","age":30}');
        function loadHandler(e){
 			//接收服务器响应的数据
            console.log(xhr.response);
        }
</script>

Ⅳ - 肆 - Ajax的属性

一 属性简介

属性描述
onreadystatechange状态发生改变的时候,能触发一些事情。
readyState详情见标注a
status数字返回状态,比如"OK"为200,"Not Found"为404等标注b
statusText字符串返回状态,比如"OK","Not Found"等
responseText以字符串返回响应。
responseXML以XML返回响应。返回的是一个XML对象,可以用DOM进行解析

(1) 标注areadyState

状态值代表的状态释义
0未初始化的状态,代表XMLHttpRequest对象被创建之前
1加载中的状态,open操作。
2已加载的状态,send操作。
3交互的状态,接收到了响应数据,但只有响应头,正文还没别接收。
4完成的状态,所有的http响应接收完成。

(2) 标注bstatus

1 信息 100-101

  1. 101:切换协议,服务器根据客户端的请求切换协议

2 成功 200-206

  1. 200:请求成功。一般用于GET与POST请求

3 重定向 300-307

  1. 301:永久重定向
  2. 302:临时重定向
  3. 303:与301类似。使用GET和POST请求查看
  4. 304:请求资源未修改,使用缓存
  5. 307:与302类似。使用GET请求重定向

4 客户端错误 400-417

  1. 404:客户端请求失败
  2. 408:请求超时

5 服务器错误 500-505

  1. 500:内部服务器错误,无法完成请求
  2. 505:服务器不支持请求的HTTP协议的版本,无法完成处理

用于请求数据的之前的验证

      var xhr=new XMLHttpRequest();
        xhr.addEventListener("readystatechange",readyHandler);
        xhr.open("GET","http://localhost:4006?user=xietian&age=30");
        xhr.send();

        function readyHandler(e){
            // xhr.status 响应消息的状态
            if(xhr.readyState===4 && xhr.status===200){
                console.log(xhr.response);
            }
        }

Ⅴ - 伍 - Ajax 使用

一 load用于本地加载文件

  • 加载本地文件必须使用GET方式

(1) 本地加载JSON文件

获取到数据之后可以进行DOM操作 ,加载的数据直接可以咋配置文件修改

        var xhr=new XMLHttpRequest();
        xhr.addEventListener("load",loadHandler);
        xhr.open("GET","./config/a.json");
        xhr.send();

        function loadHandler(){
            var obj=JSON.parse(xhr.response);
            document.documentElement.style.backgroundColor=obj.backgroundColor;
        } 

a.json

{
    "backgroundColor": "red"
}

二 promise封装ajax

这利用到了第三方模块querystring.js

querystring从字面上的意思就是查询字符串,一般是对http请求所带的数据进行解析。querystring模块只提供4个方法,在我看来,这4个方法是相对应的。

parse(str),默认以固定&=格式,解析路径,得到key/value的对象。

stringify(),系列化,把上述对象载拼成一个字符串。

第一种

    <script type="module">
        import QueryString from "./js/QueryString.js";

        function ajax(data,type="GET"){
            if(type!=="GET") type="POST";
            return new Promise(function(resolve,reject){
                let getData="";
                let postData="";
                if(type==="GET"){
                    getData="?"+QueryString.stringfiy(data);
                }else{
                    postData=QueryString.stringfiy(data);
                }
                let xhr=new XMLHttpRequest();
                xhr.open(type,"http://127.0.0.1:8001"+getData);
                xhr.onload=function(){
                    resolve(xhr.response);
                }
                xhr.onerror=function(){
                    reject("地址错误");
                }
                xhr.send(postData);
            })
        }
	//使用
        ajax({a:3,b:5}).then(function(data){
            console.log(data);
        }).catch(function(msg){
            console.log(msg)
        })
 </script>

第二种

    <script type="module">
        import QueryString from "./js/QueryString.js";

        function ajax(url,data,method="GET",type="query"){
            return new Promise(function(resolve,reject){
                if(type.toLowerCase()==="query") data=QueryString.stringify(data);
                else if(type.toLowerCase()==="json") data=JSON.stringify(data);
                var xhr=new XMLHttpRequest();
                xhr.onreadystatechange=function(){
                    if(xhr.readyState===4 && xhr.status===200){
                        resolve(xhr.response);
                    }else if(xhr.readyState===4 && xhr.status!==200){
                        reject(xhr.status);
                    }
                }
                xhr.open(method,url+"?"+(method.toLowerCase()==="get" ? data : ""));
                xhr.send((method.toLowerCase()==="get" ? "" : data));
            })
        }
//使用
    ajax("http://localhost:4006",{user:"xietian",age:30},"POST","JSON").then(function(res){
            console.log(res);
        })
 </script>

querystring.js

export default class QueryString {
    static stringify(obj, sep, eq, name) {
        sep = sep || '&';
        eq = eq || '=';
        if (obj === null) {
            obj = undefined;
        }

        if (typeof obj === 'object') {
            return Object.keys(obj).map(function (k) {
                var ks = encodeURIComponent(QueryString.stringifyPrimitive(k)) + eq;
                if (Array.isArray(obj[k])) {
                    return obj[k].map(function (v) {
                        return ks + encodeURIComponent(QueryString.stringifyPrimitive(v));
                    }).join(sep);
                } else {
                    return ks + encodeURIComponent(QueryString.stringifyPrimitive(obj[k]));
                }
            }).join(sep);

        }

        if (!name) return '';
        return encodeURIComponent(QueryString.stringifyPrimitive(name)) + eq +
            encodeURIComponent(QueryString.stringifyPrimitive(obj));
    }

    static stringifyPrimitive(v) {
        switch (typeof v) {
            case 'string':
                return v;

            case 'boolean':
                return v ? 'true' : 'false';

            case 'number':
                return isFinite(v) ? v : '';

            default:
                return '';
        }
    }
    static parse(qs, sep, eq, options) {
        sep = sep || '&';
        eq = eq || '=';
        var obj = {};

        if (typeof qs !== 'string' || qs.length === 0) {
            return obj;
        }

        var regexp = /\+/g;
        qs = qs.split(sep);

        var maxKeys = 1000;
        if (options && typeof options.maxKeys === 'number') {
            maxKeys = options.maxKeys;
        }

        var len = qs.length;
        // maxKeys <= 0 means that we should not limit keys count
        if (maxKeys > 0 && len > maxKeys) {
            len = maxKeys;
        }

        for (var i = 0; i < len; ++i) {
            var x = qs[i].replace(regexp, '%20'),
                idx = x.indexOf(eq),
                kstr, vstr, k, v;

            if (idx >= 0) {
                kstr = x.substr(0, idx);
                vstr = x.substr(idx + 1);
            } else {
                kstr = x;
                vstr = '';
            }

            k = decodeURIComponent(kstr);
            v = decodeURIComponent(vstr);

            if (!QueryString.hasOwnProperty(obj, k)) {
                obj[k] = v;
            } else if (Array.isArray(obj[k])) {
                obj[k].push(v);
            } else {
                obj[k] = [obj[k], v];
            }
        }

        return obj;
    }
    static hasOwnProperty(obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    }
}

0 - 0 - 知识点:

一 URI编码格式转换

地址栏中?后面会出现类似%E4%BD%A0%E5%A5%BD一串东西被称之为 URI编码格式

console.log(encodeURIComponent("你好"));//转换为URI编码格式
console.log(decodeURIComponent("%E4%BD%A0%E5%A5%BD"));//将URI编码格式转为字符

二 Ajax中的事件

事件要写在open()和send()前面。

load:用于本地数据的加载

timeout:设置超时事件

readystatechange:事件先于 load 事件执行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值