数据交互与ajax

Posted 一个年轻淫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据交互与ajax相关的知识,希望对你有一定的参考价值。

在Long Long Ago,那个前端还是一个切图仔的年代,那时的页面根本没有js,前端的api非常的少,页面的所有数据都来自服务器渲染,任何的页面操作都会提交form表单请求刷新页面,直到那一天,浏览器开发者给浏览器挖通了一条可以不刷新页面就从服务器获取数据的通道,以及大量的es更新,那一天前端咸鱼翻身了,这个api叫window.XMLHttpRequest,这个技术叫AJAX,全称Asynchronous javascript And XML(异步的 JavaScript 和 XML)

==前端就是一个把数据请求到然后加工然后展示给用户看的一个工作,把数据请求到就是第一步,没有数据,前端跟一条咸鱼有什么区别==

一个ajax只有发出一次请求(一份参数)获取到一次响应(一份结果)

ajax请求需要的材料是一个请求地址和请求参数
但是发起请求的数据格式有很多,这决定了后端能否拿到数据,
能决定数据格式的因素有==请求方式==和==请求体==和==Content-Type请求头==
把ajax比作寄快递,你就是拿着数据去一个叫net的快递公司寄快递,到了之后可以选择他们的车(请求方式)

》》请求方式是车,有四种车

  • GET
  • POST
  • PUT
  • DELETE

车速是一样的,但是车能装的东西有规定,而且车上的箱子也不一样

》》箱子有两种

  • 一个是拼接在请求地址后面,叫做params
  • 一个是放在一个叫请求体的地方,叫做body

GET的车上只有一个箱子,是params,其他三种车是两种箱子都有

你去寄快递,如果你选择把东西放在body箱子里寄,他会问你寄的是什么,这就是type请求头,type请求头就是告诉net公司,我寄的是什么,他会根据你寄的东西不一样,打包装,打包装是net的事,你不用管,只要如实的告诉他们无数据格式,如果你不说,他有默认的type请求头,parmas箱子不需要type请求头,因为parmas只有一个格式

Content-Type请求头有

  • application/x-www-form-urlencoded(默认请求头)
  • multipart/form-data
  • application/json
  • text/xml

因为三种因素的分类可以组合出几十种寄快递的方式
但是,会出现几种情况

  1. 寄了没发(格式不符合规定)
  2. 发了对方拿不到
  3. 对方拿到了,但是你寄的时候说错了格式,对方拿到的是一串乱码

下面列出所有常用的能顺利完成一次快递过程的方式,发请求的选择就是根据数据类型来选择的

==如果你要发下面这种key-value的并且是基础数据类型的数据==

{ 
   name: "tom"
   age: 18,
}

可以选择get,get会打包成name=tom&age=18;
也可以选择(POST | PUT | DELETE) 和 application/x-www-form-urlencoded,会被打包成跟上面一样的数据,但是是放在body的箱子里的,上面是放在params的箱子里;
还有(POST | PUT | DELETE) 和 application/json,这个特殊,往下看
选哪种要看

==如果你要发文件格式==
选择(POST | PUT | DELETE) 和 multipart/form-data

==如果你要发复杂数据类型,比如数组和对象,普通的key-value同样适用,最常用==

{ 
   obj: { name:"tom",age:18 },
   arr: [1,2,3]
}

选择(POST | PUT | DELETE) 和 application/json
但是不是像上面那么写,而是把这个数据转成json字符串格式

JSON.stringify({ 
   obj: { name:"tom",age:18 },
   arr: [1,2,3]
})

==如果你要发xml类型的数据==
选择(POST | PUT | DELETE) 和 text/xml
xml数据类型现在在前端很少见了,这个可以不理会的,就了解一下,xml数据类型在下一篇会说

也就是5种方式,减掉xml的不说,4种

下面用这四种搭配写四个jq.ajax的模板供复制使用
为什么用jq的ajax,因为自己学个ajax插件是不存在的,判断太多了,今后还会接触到另外的插件,会用就行,当然,原理还是要懂的,最下面会写一个原生的ajax请求

需要先了解ajax的F12调试手段

技术图片

F12的第6个选项Network就是浏览器的请求数据,net就是网络,work就是工作;
一切的请求在第2个红框的All都能看到,包括图片,css文件,js文件,doc文件等等;
点击第3个红框的xhr就可以筛选出ajax的所有请求;
第四框就是一个请求的列表;
第五个框headers请求信息的显示位置,里面包括了(general,responseHeaders,RequestHeaders,数据包装区);
第6的General查看请求地址,请求方式,请求头,请求参数,请求cookie的地方(还有响应头,响应cookie);
第7的responseHeaders查看请求头,请求cookie的地方;
第8的RequestHeaders查看响应头,响应cookie的地方;
第9的数据包装区,根据请求头不同有多种名字,截图是Parametes
第10是查看接口返回数据的地方

好了,上代码上截图

GET

技术图片

$.ajax({
   url:"xxxx",
   type:"get",
   // get没有请求头
   // data只能是传key-value,value不能是数组对象等复杂数据格式
   data:{
     name:"pdt",
     age:18
   }
})

post 和 application/x-www-form-urlencoded

技术图片

$.ajax({
   url:"xxxx",
   type:"post",
   // 不用写这句话因为这是默认的
   // contentType:"application/x-www-form-urlencoded",  
   // data只能是传key-value,value不能是数组对象等复杂数据格式
   data:{
     name:"pdt",
     age:18
   }
})

post 和 multipart/form-data
在这里要插入form表单提交文件的写法,进行对比

<form enctype="multipart/form-data" action="xxxx" method="post">
   <input name="file" type="file" />
   <input type="submit" value="提交" />
</form>

因为form表单提交会跳转页面,所以根本来不及截图,所以这里需要阻止跳转,阻止跳转的方式有两种,一种是iframe,一种是使用jq.from插件

iframe方式,这种方式内嵌页面,很好写不需要插件,但是在调试页面看不到请求详情

<form enctype="multipart/form-data" action="xxxx" method="post" target="iframe">
  <!-- 创建一个iframe 标签,标签加上name属性,
       form表单添加target属性等于iframe的name -->
   <iframe id="iframe" name="iframe" style="display:none"></iframe>
   <input name="file" type="file" />
   <input type="submit" value="提交" />
</form>
//获取数据
var iframe= document.getElementById(iframe);
iframe.onload = function() {
var body = (iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument).document.body;
var json = (body.innerText) ? body.innerText : ( (body.textContent) ? body.textContent : null);
//json就是iframe里请求返回的数据
console.log(json);
}

jq.form方式,需要先引入插件

<form enctype="multipart/form-data" action="xxxx" method="post" id="aa">
   <input name="file" type="file" onchange="changeUpload()"/>
</form>
function changeUpload(){
   // res就是后台返回的值
   $("#aa").ajaxSubmit(function(res) { ... }); 
   // 返回false,阻止跳转
   return false; 
}

技术图片

用jqform可以看到,请求体的格式很奇怪,如果我们用ajax怎么模拟出这个数据格式呢,在请求体你可以看到有个词叫form-data,这是个特殊的数据格式,也就是文件数据格式,js有这个api,是一个构造函数,代码如下

<input name="file" type="file" onchange="changeUpload(this.files[0])"/>
function changeUpload(file){
var formData = new FormData();
formData.append("file", file);
//还可以往formData里append更多数据
$.ajax({
   url:"xxxx",
   type:"post",
   data:formData,
   //禁止jq修改我的提交数据,这个参数一定要加
   processData: false,
   contentType : false, // 不要设置Content-Type请求头
})
}

技术图片

于是,我们用ajax成功模拟了form表单的文件提交!

post 和 application/json
我们上面一直说其他的请求头无法提交复杂数据类型的数据,现在对比下提交数据

$.ajax({
   url:"xxxx",
   type:"post",
   data:{
       obj:{ name:"name",age:18 },
       arr:[0,1,2,3],
   }
})

技术图片

如果提交上面的数据是会被后端打死的,因为这么提交是拿不到数据的
需要改成json文件提交模式

$.ajax({
   url:"xxxx",
   type:"post",
   contentType:"application/json",
   //JSON.stringify() 一定要加
   data:JSON.stringify({
       obj:{ name:"name",age:18 },
       arr:[0,1,2,3]
   })
})

技术图片

到这里jq的所有提交方式都讲完了,put,detele跟post是一样的
jq.ajax获取响应的几种写法自己去百度,他还有一个自动处理数据的dataType参数可以了解一下,还有上面的截图有个view-parsed的按钮,是浏览器自带的内容可读性优化的按钮,点一下数据会排列得好看一些

封装一个ajax,带进度条

var xhr = null;
if (window.XMLHttpRequest) {// code for Firefox, Opera, IE7, etc.
   xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {// code for IE6, IE5
   xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
// 获取上传进度
xhr.upload.onprogress = function(event) {
    var percent = Math.floor(event.loaded / event.total * 100);
    console.log(percent)
};
// 上传完成后的回调函数
xhr.onreadystatechange = function() {
    if (xhr.status === 200) {  
       console.log(xhr.responseText);
    } else { 
       console.log('上传出错');
    }
};
//open设置请求方式和请求路径
xhr.open('POST', 'url');
//设置请求头
xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded")
//send 发送
xhr.send(fd);

原生能读取上传进度,jq.ajax也行

$.ajax({
    url:'xxxx',
    ....,
    //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
    xhr: function(){ 
        myXhr = $.ajaxSettings.xhr();
          //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
        if(myXhr.upload){
            //绑定progress事件的回调函数
            myXhr.upload.addEventListener('progress',function(evt) {
                var loaded = evt.loaded; //已经上传大小情况
                var tot = evt.total; //附件总大小
                var per = Math.floor(100 * loaded / tot); //已经上传的百分比
           }, false);
        }
        //xhr对象返回给jQuery使用,固定写法
        return myXhr; 
      },
    success:function(){}
});

注意
一次ajax要请求成功,除了代码不出错
还要有几个条件
第一就是请求地址要存在,这是句废话
第二就是浏览器不跨域,(跨域的知识可以百度,也可以往后面找一篇跨域的笔记)

以上是关于数据交互与ajax的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 xcode 将快照划分为多个片段,以便让用户与每个片段进行交互?

前端与后端有哪几种ajax交互方法

Thymeleaf - 如何交互和重新加载 Javascript?

springmvc使用ajax进行数据交互时,session失效问题(@ResponseBody与session能否同时使用?)

Servlet 与 Ajax 交互一直报status=parsererror

Servlet 与 Ajax 交互一直报status=parsererror