【JavaScript】--重点解析之跨域请求
JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
JSON是用字符串来表示Javascript对象,例如可以在django中发送一个JSON格式的字符串给客户端Javascript,Javascript可以执行这个字符串,得到一个Javascript对象。
json就是js对象的一种表现形式(字符串的形式)
JSON对象语法
json语法:
- 数据在名称/值对中
- 数据由逗号分隔
- 花括号保存对象(对象需要使用大括号起来)
- 方括号保存数组(数组使用中括号括起来)
var person = {"name":"zhangSan", "age":"18", "sex":"male"}; alert(person.name + ", " + person.age + ", " + person.sex);
注意,key也要在双引号中!
JSON值:
- 数字 (整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组 (在方括号中)
- 对象 (在花括号中)
- null
var person = {"name":"alex", "age":"18", "sex":"male", "hobby":["girl", "movie", "travle"]}; alert(person.name + ", " + person.age + ", " + person.sex + ", " + person.hobby);
带有方法的JSON对象:
var person = {"name":"alex", "sex":"men", "teacher":{ "name":"tiechui", "sex":"half_men", }, "bobby":['basketball','running'], "getName":function() {return 80;} }; alert(person.name); alert(person.getName()); alert(person.teacher.name); alert(person.bobby[0]);
js接受python的json对象:
在json的编码过程中,会存在从python原始类型向json类型的转换过程,具体的转换 如下: python --> json dict object list,tuple array str,unicode string int,long,float number True true False false None null
js与django的交互
def login(request): obj={'name':"alex111"} return render(request,'index.html',{"objs":json.dumps(obj)}) #---------------------------------- <script> var temp={{ objs|safe }} alert(temp.name); alert(temp['name']) </script>
JSON与XML比较
- 可读性: XML胜出;
- 解码难度:JSON本身就是JS对象(主场作战),所以简单很多;
- 流行度: XML已经流行好多年,但在AJAX领域,JSON更受欢迎。
parse()和.stringify()
parse用于从一个字符串中解析出json对象,如 var str = '{"name":"yuan","age":"23"}' 结果: JSON.parse(str) Object age: "23" name: "yuan" 注意:单引号写在{}外,每个属性名都必须用双引号,否则会抛出异常。 stringify()用于从一个对象解析出字符串,如 var a = {a:1,b:2} 结果: JSON.stringify(a) "{"a":1,"b":2}"
跨域请求
同源策略机制
浏览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。
简单的来说,浏览器允许包含在页面A的脚本访问第二个页面B的数据资源,这一切是建立在A和B页面是同源的基础上。
如果Web世界没有同源策略,当你登录淘宝账号并打开另一个站点时,这个站点上的JavaScript可以跨域读取你的淘宝账号数据,这样整个Web世界就无隐私可言了。
jsonp的js实现
JSONP是JSON with Padding的略称。可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
JSONP就像是JSON+Padding一样(Padding这里我们理解为填充)
#---------------------------http://127.0.0.1:8001/login def login(request): print('hello ajax') return render(request,'index.html') #---------------------------返回用户的index.html <h1>发送JSONP数据</h1> <script> function fun1(arg){ alert("hello"+arg) } </script> <script src="http://127.0.0.1:8002/get_byjsonp/"></script> #-----------------------------http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): print('8002...') return HttpResponse('fun1("苑昊")')
这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义吧。
一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。
<script> function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } function fun1(arg){ alert("hello"+arg) } window.onload=function(){ addScriptTag("http://127.0.0.1:8002/get_byjsonp/") } </script>
现在将你自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调:
<script> function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } function fetch(arg){ alert("hello"+arg) } window.onload=function(){ addScriptTag("http://127.0.0.1:8002/get_byjsonp?callback=fetch") } </script> #--------------------------------http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): callback=req.GET.get('callback') print(callback) return HttpResponse('%s("yuan")'%callback)
jQuery对JSONP的实现
jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法
<script type="text/javascript"> $.getJSON("http://127.0.0.1:8002/get_byjsonp?callback=?",function(arg){ alert("hello"+arg) }); </script>
结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。
当然,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现
<script type="text/javascript" src="/static/jquery-2.2.3.js"></script> <script type="text/javascript"> $.ajax({ url:"http://127.0.0.1:8002/get_byjsonp", dataType:"jsonp", jsonp: 'callbacks', jsonpCallback:"fetch" }); function fetch(arg){ alert(arg); } </script> #--------------------------------- http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): callback=req.GET.get('callbacks') print(callback) return HttpResponse('%s("yuan")'%callback)
another way:
<script type="text/javascript" src="/static/jquery-2.2.3.js"></script> <script type="text/javascript"> $.ajax({ url:"http://127.0.0.1:8002/get_byjsonp", dataType:"jsonp", jsonp: 'callbacks', success:function(data){ alert(data) } }); </script> #-------------------------------------http://127.0.0.1:8002/get_byjsonp def get_byjsonp(req): callback=req.GET.get('callbacks') print(callback) #jQuery223015502220591490135_1477560648881 return HttpResponse("%s('yuan')"%callback)
没错,jsonpCallback就是可以指定我们自己的回调方法名fetch,远程服务接受callback参数的值就不再是自动生成的回调名,而是fetch。dataType是指定按照JSOPN方式访问远程服务。callback必须有,因为服务端根据它来去回调函数的名字,如果是自已定义的,那么就得有自定义的名字:jsonpCallback:"fetch";如果不加这个参数,则自动生成一个随机名字。
利用jQuery可以很方便的实现JSONP来进行跨域访问。