Ajax、Iframe、Jsonp
-
一、向后台提交数据的方式
- 1、通过 Form 表单提交,页面会刷新
- 2、通过 Ajax 提交,向后台偷偷发送请求,页面不刷新
-
二、Ajax
-
1、Ajax 本质是 XMLHttpRequest 对象
AJAX:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),一种创建交互式网页应用的网页开发技术方案
- 异步的 JavaScript:
使用 【JavaScript语言】 以及相关【浏览器提供类库】 的功能向服务端发送请求,当服务端处理完请求之后,【自动执行某个 JavaScript 的回调函数】
PS:以上请求和响应的整个过程是【偷偷】进行的,页面上无任何感知 - XML:
XML 是一种标记语言,是Ajax在和后台交互时传输数据的格式之一
利用 AJAX 可以做:
1、注册时,输入用户名自动检测用户是否已经存在。
2、登陆时,提示用户名密码错误
3、删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除
可以手动通过 XMLHttpRequest 对象使用,也可以利用 jQuery 使用
-
2、Ajax 发送 GET 请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>1.Ajax发送GET请求</h3> <div> <a class="btn" onclick="AjaxSubmit1();">点我</a> </div> <script src="/static/jquery-3.3.1.js"></script> <script> function AjaxSubmit1(){ $.ajax({ url:'/ajax1.html', type:'GET', data:{'p':123}, success:function(arg){ } }) } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>1.Ajax发送GET请求</h3> <div> <a class="btn" onclick="AjaxSubmit2();">点我</a> </div> <script> function AjaxSubmit2(){ // 创建XMLrequest对象 var xhr = new XMLHttpRequest(); // 设置回调函数,一定要在send前设置 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 接收完毕服务器返回的数据 console.log(xhr.responseText); } }; // 创建请求链接 xhr.open('GET', '/ajax1.html?p=123'); // 发送请求 xhr.send(null); } </script> </body> </html>
-
3、Ajax 发送 POST 请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>2.Ajax发送POST请求</h3> <div> <a class="btn" onclick="AjaxSubmit3();">点我</a> </div> <script src="/static/jquery-3.3.1.js"></script> <script> function AjaxSubmit3(){ $.ajax({ url:'/ajax1.html', type:'POST', data:{'p':123}, success:function(arg){ } }) } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>2.Ajax发送POST请求</h3> <div> <a class="btn" onclick="AjaxSubmit4();">点我</a> </div> <script> function AjaxSubmit4(){ // 创建XMLrequet对象 var xhr = new XMLHttpRequest(); // 设置回调函数 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 接收完毕服务器返回的数据 console.log(xhr.responseText); } }; // 创建请求链接 xhr.open('POST', '/ajax1.html'); // 设置请求头,不然django无法将request.body里的数据转化到request.POST里 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); // 发送请求(请求体内容) xhr.send('p=456'); } </script> </body> </html>
注:利用 XML 对象发送 POST 请求时需要手动设置请求头
-
4、"伪"Ajax:利用 Iframe+Form 模仿 Ajax 发送请求和接收回调函数
Iframe+Form 这种方式兼容性更好,历史比 Ajax 的两种版本更悠久
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>3."伪"Ajax</h3> <h6>基于Ifame+Form表单</h6> <iframe id='iframe' name="ifra"></iframe> <form id='fm' action="/ajax1.html" method="post" target="ifra"> <input type="text" name="root" value="111111"> <a onclick="AjaxSubmit5();">提交</a> </form> </div> <script> function AjaxSubmit5(){ document.getElementById('iframe').onload = reloadIframe; document.getElementById('fm').submit(); } function reloadIframe(){ // this=当前标签 // 通过js获得iframe里的值 console.log(this.contentWindow.document.body.innerHTML); // 通过jQuery获得iframe里的值 console.log($(this).contents().find('body').html()); // 伪造回调函数 var content = this.contentWindow.document.body.innerHTML; var obj = JSON.parse(content); if(obj.status){ alert(obj.message); } } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>3."伪"Ajax</h3> <h6>基于Ifame+Form表单,加载顺序bug版</h6> <iframe id='iframe' name="ifra" onload="reloadIframe(this);"></iframe> <form id='fm' action="/ajax1.html" method="post" target="ifra"> <input type="text" name="root" value="111111"> <input type="submit" value="提交"> </form> </div> <script> function reloadIframe(ths){ console.log(ths); console.log(ths.contentWindow); // 通过js获得iframe里的值 console.log(ths.contentWindow.document.body.innerHTML); // 通过jQuery获得iframe里的值 console.log($(ths).contents().find('body').html()); // 伪造回调函数 var content = ths.contentWindow.document.body.innerHTML; var obj = JSON.parse(content); if(obj.status){ alert(obj.message); } } </script> </body> </html>
注:
(1)表单提交绑定事件:document.getElementById('fm').submit()

——————————————————————

(2)不同绑定事件方法中 this 指代对象总结
方式一:在标签上进行事件绑定
<body> <div> <h6>方式一:在标签上绑定</h6> <iframe id='iframe' name="ifra" onclick="funcName(this)"></iframe> <form id='fm' action="/ajax1.html" method="post" target="ifra"> <input type="text" name="root" value="111111"> <a onclick="AjaxSubmit5();">提交</a> </form> </div> <script> function funcName(arg){ // this = window // arg = 当前标签 } </script> </body>
方式二:通过 js 进行事件绑定
<body> <div> <h6>方式二:通过js绑定</h6> <iframe id='iframe' name="ifra"></iframe> <form id='fm' action="/ajax1.html" method="post" target="ifra"> <input type="text" name="root" value="111111"> <a onclick="AjaxSubmit5();">提交</a> </form> </div> <script> function AjaxSubmit5(){ document.getElementById('iframe').onclick = funcName; document.getElementById('fm').submit(); } function funcName(){ // this = 当前标签 } </script> </body>
(3)获得 Iframe 标签里内容的方法:通过获取 Iframe 标签里的内容作为回调函数返回的内容
this :代表整个 Iframe 标签

this.contentWindow :进入 Iframe 标签的里面取 #document 的整体 window 内容页面

this.contentWindow.document :进入内层的 window 中取整个内容文档

取内层文档的 body 标签里的内容作为回调函数的返回的内容:
<1> 通过 js 获得里面的值:this.contentWindow.document.body.innerHTML
<2> 通过 jQuery 获得里面的值:$(this).contents().find('body').html()

-
三、Iframe
作用:用来嵌套别人网站
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <div> <h6>学习iframe</h6> <input type="text"> <div> <input type="text" id="url" placeholder="请输入URL"><a onclick="Test1();">查看</a> </div> <iframe id='ifm' style="height:800px; width:600px;" src="https://www.xcar.com.cn"></iframe> </div> <script src="/static/jquery-3.3.1.js"></script> <script> function Test1(){ var url = $('#url').val(); $('#ifm').attr('src', url); } </script> </body> </html>
注:点击跳转 url 时页面不刷新
利用 Iframe 标签创建一个接收通道和页面不刷新特性,加上 Form 表单可以提交数据的功能,利用 target 属性进行关联,可以模仿 Ajax 提交数据和带有回调函数的功能:

结果为:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h6>基于Ifame+Form表单</h6> <iframe id='iframe' name="ifra"></iframe> <form id='fm' action="/ajax1.html" method="post" target="ifra"> <input type="text" name="root" value="111111"> <input type="submit" value="提交"> </form> </body> </html>
from django.shortcuts import render,HttpResponse,redirect import json # Create your views here. def index(request): return render(request, 'index.html') def ajax1(request): print(request.GET) print(request.POST) print(request.FILES) # print(request.body) import json ret = {'status':True, 'message':'123'} return HttpResponse(json.dumps(ret))
-
四、Ajax 实现文件上传
-
1、通过 FormData 对象来封装用户提交的数据进行文件上传
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>4.文件上传</h3> {# 利用 formData 对象上传,但是低版本ie不支持#} <input type="file" id="img"> <a class="btn" onclick="AjaxSubmit6();">上传</a> <script src="/static/jquery-3.3.1.js"></script> <script> function AjaxSubmit6(){ // 选择器加 .files[0] 表示标签里上传的文件对象 // document.getElementById('img').files[0]; var data = new FormData(); data.append('k1','v1'); data.append('k2','v2'); data.append('k3',document.getElementById('img').files[0]); $.ajax({ url:'/ajax1.html', type:'POST', data:data, success:function(arg){ console.log(arg); }, processData:false, // tell jQuery not to process the data contentType:false // tell jQuery not to set contentType }) } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>4.文件上传</h3> {# 利用 formData 对象上传,但是低版本ie不支持#} <input type="file" id="img"> <a class="btn" onclick="AjaxSubmit7();">上传</a> <script> function AjaxSubmit7(){ var data = new FormData(); data.append('k1','v1'); data.append('k2','v2'); data.append('k3',document.getElementById('img').files[0]); // 创建XMLrequest对象 var xhr = new XMLHttpRequest(); // 设置回调函数 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 接收完毕服务器返回的数据 console.log(xhr.responseText); } }; // 创建请求链接 xhr.open('POST', '/ajax1.html'); // 发送请求 xhr.send(data); } </script> </body> </html>
注:
(1)选择器加 .files[0] 表示标签里上传的文件对象:document.getElementById('img').files[0];

(2)通过 jQuery 版上传文件时,需要添加两个参数:代表不对传送的 FormData 数据进行任何格式处理
processData:false,
contentType:false
(3)利用 formData 对象上传文件,对低版本 ie 不支持
-
2、通过 Iframe+Form 进行文件上传(推荐使用)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> <h3>4.文件上传</h3> {# 利用 Iframe+Form 上传,推荐使用#} <iframe id='iframe1' name="ifra1" style="display: none;"></iframe> <form id='fm1' action="/ajax1.html" method="post" enctype="multipart/form-data" target="ifra1"> <input type="text" name="k1"> <input type="text" name="k2"> <input type="file" name="k3"> <a onclick="AjaxSubmit8();">提交</a> </form> <script> function AjaxSubmit8(){ document.getElementById('iframe1').onload = reloadIframe1; document.getElementById('fm1').submit(); } function reloadIframe1(){ // 通过js获得iframe里的值 console.log(this.contentWindow.document.body.innerHTML); // 通过jQuery获得iframe里的值 console.log($(this).contents().find('body').html()); // 伪造回调函数 var content = this.contentWindow.document.body.innerHTML; var obj = JSON.parse(content); console.log(obj); } </script> </body> </html>
注:需要将 Iframe 标签设置样式 style="display: none;"
-
3、图片上传实时预览
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .btn{ display: inline-block; padding: 5px 10px; background-color: coral; color: white; } </style> </head> <body> {# 利用 Iframe+Form 上传,推荐使用#} <iframe id='iframe1' name="ifra1" style="display: none;"></iframe> <form id='fm1' action="/upload_img.html" method="post" enctype="multipart/form-data" target="ifra1"> <input type="file" name="k3" onchange="uploadFile();"> </form> <h3>预览</h3> <div> <div id="preview"></div> </div> <script src="/static/jquery-3.3.1.js"></script> <script> function uploadFile(){ document.getElementById('iframe1').onload = reloadIframe1; document.getElementById('fm1').submit(); } function reloadIframe1(){ {#console.log(ths);#} {#console.log(ths.contentWindow);#} // 通过js获得iframe里的值 console.log(this.contentWindow.document.body.innerHTML); // 通过jQuery获得iframe里的值 console.log($(this).contents().find('body').html()); // 伪造回调函数 var content = this.contentWindow.document.body.innerHTML; var obj = JSON.parse(content); console.log(obj.data); // 创建一个img标签,预览图片使用 var tag = document.createElement('img'); // img标签的src属性赋值为图片的在服务器端的静态路径 tag.src = obj.data; // 需要清空之前上传的图片再追加新的图片 $('#preview').empty().append(tag); } </script> </body> </html>
from django.shortcuts import render,HttpResponse,redirect import json def upload(request): return render(request, 'upload.html') def upload_img(request): import os import uuid nid = str(uuid.uuid4()) ret = {'status':True, 'data':None, 'message':None} obj = request.FILES.get('k3') file_path = os.path.join('static', nid+obj.name) # 拿到文件所在服务器的静态目录路径 f = open(file_path, 'wb') for line in obj.chunks(): f.write(line) f.close() ret['data'] = file_path return HttpResponse(json.dumps(ret))
注:
(1)上传的图片需要保存在服务器静态目录下,返回前端的也得是服务器的静态路径
(2)为了防止文件重名,可以在文件名前加入uuid进行拼接
(3)前端利用代码创建 img 标签,src 属性为图片的服务器静态路径,展示之前要先清空原先的图片
-
五、Jsonp:跨域 Ajax
Jsonp 是随机生成 script 块添加到 head 里,其中 src 属性为远程网站的 url,然后再移除这个 script 标签,用来突破浏览器的同源策略,可以跟不同的网站进行交互的一种方式
但是对方返回数据的时候,前面一定包裹一个函数名,本地也得有相应函数来对返回的数据进行处理
注:
(1)浏览器的同源策略,XMLHttpRequest 对象往本地发请求,浏览器可以接收返回的信息,但是往其他域名发送请求,对方服务器可以收到请求,但是返回的信息会被浏览器拦截,不能接收
(2)具有 src 属性的标签一般都不遵循同源策略,可以利用这一机制突破同源策略,例如:img、script、iframe 等
(3)jsonp 本质是GET请求,只能发送GET请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="发送3" onclick="submitJsonp3();"> <script> function submitJsonp3(){ var tag = document.createElement('script'); tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403'; document.head.appendChild(tag); document.head.removeChild(tag); } // 必须与返回数据包裹的函数名一致 function list(arg){ console.log(arg); } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="发送4" onclick="submitJsonp4();"> <script src="/static/jquery-3.3.1.js"></script> <script> function submitJsonp4(){ $.ajax({ url:'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403', type:'GET', dataType:'jsonp' }) } // 必须与返回数据包裹的函数名一致 function list(arg){ console.log(arg); } </script> </body> </html>
Jsonp 总结:
1、在 ajax 里设置参数 jsonp 和 jsonpCallback
jsonp:'callback',
jsonpCallback:'list' --> 此处填返回数据的包裹的函数名,如果对方可以动态获取函数名,那么这里可以自己设置函数名,以 "list" 为例
2、对方服务器最好可以动态获取接收请求发送过去的函数名:request.GET.get('callback')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="发送4" onclick="submitJsonp4();"> <script src="/static/jquery-3.3.1.js"></script> <script> function submitJsonp4(){ $.ajax({ url:'http://127.0.0.1:9000/xiaokai.html', type:'GET', dataType:'jsonp', jsonp:'callback', jsonpCallback:'list' }) } function list(arg){ console.log(arg); } </script> </body> </html>
from django.shortcuts import render,HttpResponse # Create your views here. def xiaokai(request): name = request.GET.get('callback') return HttpResponse('%s("小云");' %(name,))
注:设置响应头方法
from django.shortcuts import render,HttpResponse # Create your views here. def xiaobo(request): obj = HttpResponse('小云') obj['Access-Control-Allow-Origin'] = '*' return obj

浙公网安备 33010602011771号