Ajax——由浅入深

本篇文章将会涵盖Ajax的的创建、使用、与服务器的交互、ajax封装,ajax的send发送类型,请求头与响应头,readystatechange来进行讨论。

1.浅谈Ajax

1.1、web渲染方式

        在谈Ajax之前,先说一下web的渲染方式,页面渲染方式分为ssr—服务端渲染,与scr—客户端渲染:

ssr(服务端渲染):

        简单理解就是浏览器发送请求后,服务器把客户端网页和数据在后台渲染解析,之后把渲染后的结果返回客户端。也就是说,网页是跳转式的,会造成页面的刷新

csr(客户端渲染):

        浏览器发送页面请求,服务器返回的是一个模板页面,浏览器从上至下解析过程中需要发送ajax请求获取数据,最后再调用模板引擎(art-template等)渲染HTML结构,并把渲染后的结果添加到页面指定容器中。。。。网上给出的解释,就是不跳转刷新页面。

        ssr与csr各有优缺点,根据需求来决定怎么用吧,具体不谈了,毕竟今天主要是Ajax。

1.2、Ajax

        说了这么一大堆,其实就是想说Ajax是csr客户端渲染,使用Ajax可以实现:

  • 不刷新页面更新网页
  • 在页面加载后从服务器请求与接收数据
  • 在后台向服务器发送数据
  • 用于在后台与服务器交换数据

创建Ajax顺序

我们与服务器通信的API就是XMLHttpRequest(为什么叫XML,可以去搜一下挺有意思的)

  1. 新建XMLHttpRequest对象
    1. let xhr = new XMLHttpRequest();
    2. IE7以下 let xhr = new ActiveXOBject('Microsoft.XMLHTTP');
  2. 打开要发送的地址通道,
    1. xhr.open('GET',地址,同步/异步)
  3. 给XMLHttpRequest对象增加侦听器,用来侦听各种情况,包括各种链接状态
    1. xhr.addEventListener('load',侦听函数)
  4. 如果没有要发送的内容,直接send()
    1. xhr.send();

2.Ajax创建与使用

先看一下Ajax的使用,再进行详细分析

首先用node创建一个服务器,用于处理Ajax使用get/post发送的内容

const http = require('http');
//querystring中有node自带的解析字符串的方法,不过现在这个方法已经弃用,暂时先用着
const querystring = require('querystring')
http.createServer(async function(req,res){
res.writeHead(200,{
    "Content-Type":"text/html;charset=utf-8",
    //设置ajax跨域能够被谁访问,*代表所有(先这样写)
    "Access-Control-Allow-Origin":"*"
});
let body,params;
params=req.url.split('?')[1];
//如果params有内容,则是get发送;接收到的信息需要解码,再通过自带的解析字符串方法进行解析
if(params&&params.trim()) params=querystring.parse(decodeURIComponent(params));
//req.method:获取请求方式
if(req.method.toLowerCase()==='post'){
        body = await getData(req);
        try {
            body = JSON.parse(body);
        } catch (e) {
            body = querystring.parse(decodeURIComponent(body))
        }
}
//服务器返回给请求客户端的内容,如果不是传递的字符串,就需要使用JSON.stringify转换为JSON字符串型
//返回转换好的内容,测试是否获取成功
params ? res.end(JSON.stringify(params)) : res.end(JSON.stringify(body));
}).listen(4010);

//处理由post传入的数据
function getData(req) {
    return new Promise(function (resolve, reject) {
        var data = ""
        //监听事件,data为数据接收过程的事件,参数就是接收的post传过来的内容
        req.on("data", function (_data) {
            //传入的数据是一个Buffer二进制流,可以使用强转为字符串,转换格式
            data += _data;
        });
        //接收完成后,将数据返回出去
        req.on("end", function () {
            resolve(data);
        })
    })
}

2.1、Ajax使用GET向服务端发送

var xhr = new XMLHttpRequest();
//load先暂时使用,稍后使用readystatechange
xhr.addEventListener('load',loadHandler);
xhr.open('GET','http://10.9.46.232:4010?age=22');//open为地址栏传参
xhr.send();//
function loadHandler(e){
    console.log(xhr.response);//打印服务器返回的值
    //{"age":"22"}
}

2.2、Ajax使用POST向服务器发送内容

let xhr = new XMLHttpRequest();
xhr.addEventListener('load',loadHandler);
xhr.open('POST','http://10.9.46.232:4010?age=30');
xhr.send("tel=15153808888&email=121@qq.com");
function loadHandler(e){
	console.log(xhr.response);
}

3.send可以发送的数据类型 

这的send就是xhr中的send,可以发送多种数据类型,其中有一些易于理解的就只列出不进行讨论了

3.1、DOMString data——文本数据(忽略)

3.2、Document data——文档对象(忽略)

3.3、ArrayBuffer data——类型化数组

ArrayBuffer是不能直接进行使用的,需要使用Uint8Array、Uint16Array等进行传送,并且post传送的内容虽然不会暴露在地址栏中,但是还是可以在网络中查找到发送的内容,所以,可以在客户端发送之前进行一个小小的加密,到服务端再进行解密

Uint8Array

正整形8位数组,可以当做一个ASCII码数组,最大只到255,输入非数值就是0,非整数会去掉小数部分,输入负数就会产生借位(-1 就是 255),用来传递数字、字符

小案例:

//index.html
        //str为要发送的数据
        let str ='i love javascript';
        //取出每一位,转换为UniCode编码格式,并使用异或100小小加密
        let arr=str.split('').map(item=>{
            return item.charCodeAt(0)^100;
        })
        //将数组存入Uint8Array中
        arr =new Uint8Array(arr);

        var xhr=new XMLHttpRequest();
        xhr.addEventListener("load",loadHandler);
        xhr.open("POST","http://localhost:4010");
        xhr.send(arr)//通过小黄人(xhr)发出

        function loadHandler(e){
            console.log(xhr.response);
        }


//node服务器中,使用上边那个node服务器接收post数据就可,只需要把获取数据的内容修改一下,我直接书写要修改的内容
function getData(req) {
    return new Promise(function (resolve, reject) {
        var data = "";
        req.on("data", _data => {
            // Unit8Array解析和异或
            for (var i = 0; i < _data.length; i++) {
//发送过来的数据,为二进制流数据,首先进行异或100解密,再使用fromCharCode将UniCode格式转换
                data += String.fromCharCode(_data[i] ^ 100);  
          }
            req.on("end", () => {
                console.log(data)
                resolve(data);
            })
        })
    })
}

//网络截取到的post发送数据内容:DD
//服务解析后的内容:i love javascript

Unit16Array

可以用来发送汉字,正整形16位数组,将字符串转换为这种数组,发送到服务端,再由服务端进行解析,发送过去的数据每一个会被拆分成两个 8 位的,并且位置会颠倒,例如'一',发送过去就是 00 4e,传送过去的都会被转换成8位一组的十六进制数据

案例:

//index.html
        var str="你好我是中文格式";
     
        var arr=str.split("").map(item=>{
        // 将字符串中的字符转换为Unicode编码格式的数据,并进行异或操作
           return  item.charCodeAt(0)^100;
           
        })
         arr=new Uint16Array(arr);

        var xhr=new XMLHttpRequest();
        xhr.addEventListener("load",loadHandler);
        xhr.open("POST","http://localhost:4020");
        xhr.send(arr)

        function loadHandler(e){
            console.log(xhr.response);
        }

//node服务器接收

for (var i = 0; i < _data.length; i += 2) {//二进制流
//汉字接收有些麻烦,解释起来太多了,可以分解打印看一下
data += String.fromCharCode(parseInt("0x" + _data[i + 1].toString(16).padStart(2, 0) + _data[i].toString(16).padStart(2, 0), 16) ^ 100);
                }

3.4、Blob data——二进制大对象

文件发送类型,像form表单中的file发送,可以使用files获取到file中的文件列表,并通过Blob data发送,但是服务器解析困难,后期可以使用fileReader进行处理。。。

3.5、FormData data——数据对象

获取的数据时form中的每一项的name值对应的value所组成的迭代器,Ajax可直接send发送,但是服务器在解析后,会多出许多其他信息,未来有插件进行解决FormData解析问题,现阶段,因为是迭代器,可取出内容,转换为对象进行发送

还有一点,在未来,使用Vue和react不允许使用,因为Vue和react是操作虚拟Dom的,不可直接操作Dom,所以,不能使用FormData

现阶段设置FormData内容,

let o ={a:1,b:2,c:3}
let fd = new FormData();
for(var key in o){
    fd.set(key,o[key]
}
fd中的方法:delete,entries,forEach,get,getAll,has,heys,set,values

4.请求头,响应头

在这里插入图片描述

 嫖一下大神的图,进行解释,感谢感谢。。。

  • 请求头的设置,必须放在open之后,send之前,请求头中的数据比send更早到达服务器,可以将一些数据更早的稿纸服务器,来验证是否可以继续发送后面的数据
    •  xhr.setRequestHeader(请求头名称,请求头值);
    • xhr.open("POST","http://localhost:4020");
      xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
      xhr.send();
  • 服务器获取请求头
    • req.headers;
      • 打印内容即为设置的请求头,headers相当于一个对象,里面有很多信息,包括传过来的所有请求头,可以将指定的值取出来
  • 发送非指定请求头会报错,想要发送,必须在服务器设置允许请求头跨域
    • res.writeHead(200,{
          "Content-Type":"text/html;charset=utf-8",
          "Access-Control-Allow-Origin":"*",//Ajax跨域设置
        "Access-Control-Allow-Headers":"*",// 请求头跨域
      })
  • 设置自定义请求头

    • 自定义的请求头,首字母必须以X开头,并且用-连接单词,每个单词首字母大写

    • 服务端获取指定的请求头

      • console.log(req.headers["x-ids"]);

        •  传过来接收的时候都是小写字母

  • 设置自定义响应头

    • res.writeHead(200,{
          "Content-Type":"text/html;charset=utf-8",
          "Access-Control-Allow-Origin":"*",//Ajax允许跨域
          "Access-Control-Allow-Headers":"*",// 请求头跨域
          "Access-Control-Expose-Headers":["X-Name","X-Age"],// 允许发送的响应头名称,没有的设置了也发不过去
          "X-Name":"xiaowang", // 自定义响应头,命名规则和请求头一样
          "X-Age":25
      })
  • 客户端接收响应头

    • // Ajax中侦听的 load 事件的处理函数
      function loadHandler(e){
          console.log(xhr.getAllResponseHeaders()); // 所有的响应头,不包括那几个Access 的权限设置的响应头
          console.log(xhr.getResponseHeader("x-age")) // 单独获得其中的一个部分
      }
      //getResponseHeader获取头部指定的属性值
      //getAllResponseHeaders获取所有头部属性
      //setRequestHeader 设置头部属性,必须在open以后,send以前写入
      //如果需要获取服务端返回的自定义响应头,需要服务器设置
      res.setHeader("X-Session-Code", "aaa");
      res.setHeader(Access-Control-Expose-Headers","x-Session-Code")

 5.readystatechange事件

load事件为加载完成后执行,ajax发送请求是有过程的,所以,使用load不能满足需求,可使用readystatechange,请求一般分为4步,第2步时,响应头到达

  • 使用这个事件代替load事件

xhr.addEventListener("readystatechange",readystateHandler);
// 我们认为请求消息一共有 5 步
值     状态                描述
0	   UNSENT             代理被创建,但尚未调用open()方法
1      OPENED             open()方法已经被调用
2      HEADERS_RECEIVED   send()方法已经被调用,并且头部和状态已经可获得
3      LOADING			  下载中;responseText 属性已经包函部分数据
4      DONE   			  下载操作已完成
// 这个事件在通信的时候一共会触发四次
1. 发送请求,请求头被发送
2. 响应头消息传输过来
3. 下载响应消息,服务端发送的数据
4. 下载完成,load 事件就是在这一步触发

status状态:1XX:信息,2XX:成功,3XX:重定向,4XX:客户端错误,5XX:服务器错误

function readystateHandler(e){
    // console.log(xhr.status,xhr.readyState,xhr.getAllResponseHeaders())
    if(xhr.status===200 && xhr.readyState===2){ // status 响应头中的状态码, readyState 触发事件时所处的状态
        console.log(xhr.getAllResponseHeaders());
        // xhr.abort();

    }else if(xhr.status===200 && xhr.readyState===4){
        console.log("下载完成",xhr.response)
    }else if(xhr.status!==200 && xhr.readyState===2){

    }
    console.log("aa")
}

 6.Ajax封装

async function init() {
    // var res=await ajax("http://localhost:4020");
    var res = await ajax("http://localhost:4020", { method: "post", body: JSON.stringify({ a: 10 }) })
    console.log(res)
}
// ajax封装,传入参数:地址,对象:请求方式,默认get,内容,请求头,
function ajax(url, { method = "get", body = null, headers = null } = { method: "get" }) {
    return new Promise(function (resolve, reject) {
        // 创建ajax,在open中放入请求方式与地址
        var xhr = new XMLHttpRequest();
        xhr.open(method, url);
        //  请求头,写在open之后,send之前,如果有请求头,则拿出设置请求头 
        if (headers) Object.keys(headers).forEach(k => {
            xhr.setRequestHeader(k, headers[k]);
        })
        // 如果body存在,发送出body,如果不存在不发送
        body ? xhr.send(body) : xhr.send();
        xhr.onreadystatechange = function () {
            // 请求已经完成并且成功
            if (xhr.readyState === 4 && xhr.status === 200) {
                var d;
                try {
                    d = JSON.parse(xhr.response);
                } catch (e) {
                    d = xhr.response;
                }
                resolve(d)
            } else if (xhr.readyState === 2 && ~~(xhr.status / 100) === 4) {
                reject(xhr.status);
            }
        }
        xhr.onerror = function (e) {
            reject(e)
        }
    })
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书秉承作者倡导的“向上提升,向下扎根”的理念,将概念和实际操作讲解与一个“吴哥窟之旅”动态网站的开发细节相结合,并以图示化教学方式引领您全程体验Dreamweaver CS3在网页设计和Web 2.0动态网站开发中各个方面的强大功能及实际应用技巧。 全书共分5部分。概念篇——完整介绍Dreamweavet CS3的特色、功能、安装、设置及编辑环境,并对网页与网站的概念、网站开发流程、建网前的准备与分析等进行一一介绍;基础篇——由浅入深介绍网页制作中文、图像、超链接的设置、表格的使用、CSS应用等重要课题;进阶篇——深入探讨网页地图与AP元素、页框网页、网站相簿、窗体、网络多媒体应用、样版等重要技术以及网站的上传与维护技术:互动篇——重点介绍行为设置、程序代码片段、扩充程序的应用,Spry framework与Dreamweaver Ajax技术框架相结合,为网页加入Web 2.0元素,结合ASP开发出数据库驱动的动态网站;附录篇——对常见服务器错误信息进行整理,并给出解决方法,让所有困难都迎刃而解。 光盘给出书中案例的源文件、结果文件和中间关键文件,方便对照学习。 本书系台湾大侠支招,适合网页设计与制作人员;网站建设与开发人员;大中专院校相关专业师生;网页制作培训班学员;个人网站爱好者;Dreamweaver自学读者。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值