Js_Dom(9)__Dom基础<Ajax请求>

来源:互联网 发布:教师网络研修的弊端 编辑:程序博客网 时间:2024/06/14 05:31

什么是AJAX

AJAX 是一种用于创建快速动态网页的技术

传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面

AJAX通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新

有很多使用 AJAX 的应用程序案例:新浪微博、Google 地图、开心网等等等


底层原理:







AJAX的使用

1.请求对象的创建(做浏览器兼容)

 

所有现代浏览器new XMLHttpRequest()

老版本的浏览器(IE5,IE6) new ActiveXObject("Microsoft.XMLHTTP")

 

//如果浏览器有XMLHttpRequest这个对象就创建

if(window.XMLHttpRequest){

http=new XMLHttpRequest()

}

//没有就创建ActiveXObject

else{

http=new ActiveXObject("Microsoft.XMLHTTP")

}


2.发送请求

http.open(method,url,async)//1.方法 2.url  3.异步否

http.send()//发送

 

3.监听状态

http.readyState//0:请求没有初始化 1:服务器建立连接 2:请求已接受 3:请求处理ing 4:请求完成,响应已经就绪

http.status//200:"OK" 404:错误

http.onreadystatechange=function(){}//每次当状态改变都会调用这个方法

 

4.响应

http.responseXML//如果服务器响应的是xml,就用这个属性

http.responseText//如果服务器响应的是非xml,就用这个

 

<body>

<button id="btn1">发送</button>

<script>

window.onload=function(){

var btn=document.querySelector('#btn1')

btn.onclick=function (){

 

if(window.XMLHttpRequest){

http=new XMLHttpRequest()

}

//没有就创建ActiveXObject

else{

http=new ActiveXObject("Microsoft.XMLHTTP")

}

 

 

http.open('GET','ajax.txt',true)

http.send()

 

http.onreadystatechange=function(){

if(http.readyState==4 && http.status==200){

         console.log(http.responseText)

         }else{console.log(http.readyState);console.log(http.status)}

}

}

}

</script>

</body>




GET,POST

1.GET的信息放在url中暴露出来,可以被本地缓存(根据url)

http.open(‘GET’,’test.txt?name=jack&pwd=123’,true)//这时候,在服务器的req.url里就可以得到用户名和密码(jack如果写成中文,就要用encodeURI(xxx)这样服务器才不是乱码)

把服务器的数据改了,再次刷新,会发现浏览器得到的数据并没有改变,咦~~其实是因为,请求一样时,浏览器是从缓存中提取的数据(用ie测试,谷歌可能不会有这个效果)//解决方案,在请求url后面加上一个随机数或者时间戳,保证每次的url唯一



2.POST

① post请求,传递的数据不要放在url中,数据放在send()方法里//send(‘name=karen&age=46’)

② post请求,要在head中告诉后端发送的数据格式(enctype)//忘了就查表单的编码格式

③ post请求不会有缓存

 

后端代码:

var http=require('http')

var fs=require('fs')

var querystring=require('querystring')

 

http.createServer(

function(req,res){

  if(req.url=='/'){

           fs.readFile('ajax3/ajax3.html',function(err,data){

                   res.end(data.toString())  

                      })

            }

         else if(req.method.toUpperCase()=='POST'){

                     var postArg='';

                    req.on('data',function(data){postArg+=data})

                    req.on('end',function(){

                             var userData=querystring.parse(postArg)

                    console.log(userData)

                             var person1_json="{'你的密码':"+userData["pwd"]+"}"

                             res.end(person1_json)

                             })

                            } 

           }

).listen(8081)

前端代码:

<body>

<button id="btn1">post请求</button>

<formenctype="application/x-www-form-urlencoded">

<script>

var btn1=document.getElementById('btn1')

btn1.onclick=function(){

         varhttp;

         if(window.XMLHttpRequest){http=newXMLHttpRequest()}

         else{http=newActiveXObject("Microsoft.XMLHTTP")}

         http.open('POST','ajax3.txt',true)

         http.setRequestHeader('content-type','application/x-www-form-urlencoded;charset=utf-8')

         http.send("name=jack&pwd=123")

         http.onreadystatechange=function(){

                   if(http.readyState==4&& http.status==200){

                            console.log(http.responseText)

                            }else{console.log(111)}   

                   }

         }

</script>

</body>




数据解析

这里我们用假数据讲解数据解析(引出跨域问题)

1.得到数据以后,我们怎么把数据通过DOM操作展示出来呢

最直接的办法就是把返回的数据,通过字符串的方法各种剪裁然后展示

得到的数据:var person=“{name:jack,age:18,info:[‘html’,’css’,’js’,’php’]}”

解析:

var name=person.slice(6,10)..........

Document.get...(‘name’).innerHTML=name..........

2.JSON解析

//为何json解析:因为做开发时json的数据多如牛毛

①一层

<body>

<button>登录</button><br/>

<p id="name"></p>

<p id="age"></p>

<p id="phoneNumber"></p>

 

<script>

document.querySelector("button").onclick=function(){

        

varpersonstr='{"name":"jack","age":"19","phoneNumber":"18282832341"}'

var person_json=JSON.parse(personstr)

document.getElementById('name').innerHTML='姓名:'+person_json.name

document.getElementById('age').innerHTML='年龄:'+person_json.age

document.getElementById('phoneNumber').innerHTML='电话:'+person_json.phoneNumber

 

}

</script>

</body>

 

②两层

<body>

<button>登录</button><br/>

<p id="name"></p>

<p id="age"></p>

<p id="phoneNumber"></p>

<p id="it"></p>

<script>

document.querySelector("button").onclick=function(){

        

varpersonstr='{"name":"jack","age":"19","phoneNumber":"18282832341","it":["html","css","js","php"]}'

var person_json=JSON.parse(personstr)

 

document.getElementById('name').innerHTML='姓名:'+person_json.name

document.getElementById('age').innerHTML='年龄:'+person_json.age

document.getElementById('phoneNumber').innerHTML='电话:'+person_json.phoneNumber

for (i in person_json.it){

         document.getElementById('it').innerHTML+="  "+person_json.it[i]

    }

        

}

</script>

</body>

③管你多少层

<body>

<button>登录</button><br/>

<p id="name"></p>

<p id="age"></p>

<p id="phoneNumber"></p>

<p id="it"></p>

<p id="QQ"></p>

<script>

document.querySelector("button").onclick=function(){

        

varpersonstr='{"name":"jack","age":"19","phoneNumber":"18282832341","it":["html","css","js","php"],"QQ":[{"id":"2733464076","pwd":"xxx1"},{"id":"12345","pwd":"xxx2"}]}'

var person_json=JSON.parse(personstr)

console.log(person_json)

document.getElementById('name').innerHTML='姓名:'+person_json.name

document.getElementById('age').innerHTML='年龄:'+person_json.age

document.getElementById('phoneNumber').innerHTML='电话:'+person_json.phoneNumber

for (i in person_json.it){

         document.getElementById('it').innerHTML+="  "+person_json.it[i]

    }

for (i in person_json.QQ){

        

         for(j inperson_json.QQ[i]){

         document.getElementById('QQ').innerHTML+="  "+person_json.QQ[i][j]

         }

        

    }       

        

}

</script>

</body>

④结合服务器

html:

 

<body>

<button>登录</button><br/>

<p id="name"></p>

<p id="age"></p>

<p id="phoneNumber"></p>

<p id="it"></p>

<p id="QQ"></p>

<script>

document.querySelector("button").onclick=function(){

         //兼容性

         varhttp;

         if(window.XMLHttpRequest){http=newXMLHttpRequest()}

         else{http=newActiveXObject("Microsoft.XMLHTTP")}

        

         //请求数据

         http.open('GET','ajax4.txt',true)

         http.send()

        

         //得到数据

         http.onreadystatechange=function(){

                   if(http.readyState==4&& http.status==200){

                            console.log(http.responseText)

                           

                            //解析数据并展示

                            ui(http.responseText)

                           

                            }else{console.log(111)}

                           

                   }

                  

 

function ui(personstr){

var person_json=JSON.parse(personstr)

console.log(person_json)

document.getElementById('name').innerHTML='姓名:'+person_json.name

document.getElementById('age').innerHTML='年龄:'+person_json.age

document.getElementById('phoneNumber').innerHTML='电话:'+person_json.phoneNumber

for (i in person_json.it){

         document.getElementById('it').innerHTML+="  "+person_json.it[i]

    }

for (i in person_json.QQ){

         for(j inperson_json.QQ[i]){

         document.getElementById('QQ').innerHTML+="  "+person_json.QQ[i][j]

         }

  }  

}

        

}

</script>

</body>

服务器:

var http=require('http')

var fs=require('fs')

 

http.createServer(

function(req,res){

  

  if(req.url=='/'){

           fs.readFile('ajax4/ajax4.html',function(err,data){

                   res.end(data.toString())  

                      })

            }

        

         elseif(req.method.toUpperCase()=='GET'&&req.url=='/ajax4.txt'){

                    res.end('{"name":"jack","age":"19","phoneNumber":"18282832341","it":["html","css","js","php"],"QQ":[{"id":"2733464076","pwd":"xxx1"},{"id":"12345","pwd":"xxx2"}]}')

                    } 

           

         }

 

).listen(8081)

 

⑤MV:model-view 

⑥:解析到这里你应该发现一个问题:为什么每次,我都是把前端的界面通过服务器发送过来,再做AJAX局部数据请求并展示,可以直接自己写个前端界面(代码一样),然后来我的服务器拿数据刷新局部界面吗?






跨域


1.跨域,

一个域名下的文件,AJAX去请求另外一个域名下的文件就跨域了,它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制

2.怎么看当前界面是不是属于其他网站的呢

主要从这几个参数看是否同源

所谓同源是指,域名,协议,端口均相同(任一一个不同都属于跨域)

http://www.hq.com?name=jack想访问https://www.baidu.com?ajax.php

http协议不同:http  https

子域名同:www  www

主域名不同:hq  baidu




3.JSONP解决跨域

①JSONP:JSON with Padding //嵌入的JSON数据

②除了AJAX可以获取资源,flash也可以获取资源,还有一个就是我们最常见的也可以获取资源---标签!  img标签 link 标签 script标签等等

③JSONP不是新东西,就是以前学过的东西,做点小操作实现跨域

⑤复习script标签

script标签可以加载资源:<scriptsrc=’test.js’></script>

 

script标签加载资源没有跨域问题:用百度地图的API的时候,<scripttype="text/javascript"src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥">  

 

<script src=’txt.js’></script>//这里我们加载的是不是js文件呢?

 

文件类型:文件是什么类型的由谁来决定? 不是后缀,如果是后缀的话,那我们随便把txt文件后缀改为png,那岂不是txt数据就变成图片数据了,后缀只是取了个名字让别人或者别的程序读,告诉依赖者我的内容可能是什么格式的//把js文件后缀改了,让script标签加载

文件的类型由文件内容本身决定

 

<script src=’test.txt’></script>  src里的东西,不管是什么格式,它都会去加载,只是,加载了之后我们要使用得是js的东西

 

⑥JSONP的原理

如果加载的js资源里是这样滴

var a=[10,20,30]

那我们加载以后想使用20,直接叫一下a再取对应下标就可以得到,

但是,如果js资源里是这样的[10,20,30]

这时候我们依然可以加载到这个数组数据,但是想使用20,该如何使用(最悲剧的事情就是工资到手了不能用)

 

没有名字还想用,瞬间想到有一种情况就是这样的,函数调用时,传递的回调函数就可以没有名字,因为函数为它取了一个形参名

因此我们可以这样做,就能达到不给数组取名字就能使用它

js文件:

fn([10,20,30])

html文件:

function fn(arg){//使用数据20}

<script src=’test.js’></script>

 

 

 

 

 

这,就是JSONP的原始模式:在资源加载进来之前定义好一个函数,这个函数接受一个参数(数据),函数里面利用这个参数就可以使用数据了,然后需要的时候通过script标签加载对应的远程文件资源,当远程文件资源被加载进来以后,就会去执行我们之前定义好的函数,并且把数据当做这个函数的实参传入//Padding的意思就是把数据嵌入到代码块中(函数调用)

 

 

上面例子有一个问题,数据是页面加载的时候去加载的数据, 而我们的局部请求往往都是用户动了界面哪个地方数据才来

解决方法:在用户的事件触发时,创建script标签去加载数据

Js文件:

fn([10,20,30])

html文件:

function(arg){xxx1.innerHTML=arg[1]}

document .getxxx(‘btn’).onclick=function(){

varscript1=document.createElement(‘script’)

script1.src=’test.js’

document.body.appendChild(acript1)

}

 

但是,还有一个问题,如果有两个数据呢,比如,用户点了一个按钮局部请求并展示了20,又点击了另外一个按钮,局部请求并想展示另外一个数据,这时候,我们马上想到可以多写一个函数

html文件:

 

<body>

<button id="btn1">中文</button>

<p id="p1"></p>

<button id="btn2">Eglish</button>

<p id='p2'></p>

<script>

function fn1(arg){

         varp1=document.getElementById("p1").innerHTML=arg[1]

         }

function fn2(arg){

         varp1=document.getElementById("p2").innerHTML=arg[1]

         }       

        

var btn1=document.getElementById("btn1")

var btn1=document.getElementById("btn1")

 

btn1.onclick=function(){

         varscript1=document.createElement("script")

         script1.src='http://192.168.0.120:8081/test.js?page=1'

         document.body.appendChild(script1)

         }

btn2.onclick=function(){

         varscript2=document.createElement("script")

         script2.src='http://192.168.0.120:8081/test.js?page=2'

         document.body.appendChild(script2)

         }       

</script>

</body>

js文件:

var http=require('http')

http.createServer(

function(req,res){

         console.log(req.url)

         if(req.url=='/test.js?page=1'){res.end("fn1(['','',''])")}

         else{res.end("fn2(['one','two','three'])")}

         }

).listen(8081)

 

这时候问题就来了,假设你写界面的时候,又有一个按钮了,你是不是又要写一个函数fn3,然后又一天又有一个按钮,你又要写一个函数fn4,每有一个业务你都要去写,假设有10万个按钮呢?怕不怕?  最可怕的不是累死,是后端的人把你打死,因为你每次有新的按钮,你都要为它取一个名字,然后去找后端开发的再多加一个接口,还必须得把函数的名字都取一样:fn1,fn2...,项目进行时还非得等到你写到哪里了,后端才开始写.

 

⑦JSONP的使用

我们最后一次优化是把回调函数的名字传给服务器,前端把回调函数取什么名字,后端就直接拿过来用

html文件:

<body>

<button id="btn1">中文</button>

<p id="p1"></p>

<button id="btn2">Eglish</button>

<p id='p2'></p>

<script>

function fn1(arg){

         varp1=document.getElementById("p1").innerHTML=arg[1]

         }

function fn2(arg){

         var p1=document.getElementById("p2").innerHTML=arg[1]

         }       

        

var btn1=document.getElementById("btn1")

var btn1=document.getElementById("btn1")

 

btn1.onclick=function(){

         varscript1=document.createElement("script")

         script1.src='http://192.168.0.120:8081/test.js1?callback=fn1'

         document.body.appendChild(script1)

         }

btn2.onclick=function(){

         varscript2=document.createElement("script")

         script2.src='http://192.168.0.120:8081/test.js2?callback=fn2'

         document.body.appendChild(script2)

         }       

</script>

</body>

 

Js文件:

var http=require('http')

var url=require('url')

http.createServer(

function(req,res){

         //console.log(url.parse(req.url))

         varcallback=url.parse(req.url).query.replace('callback=','')

         varpathname=url.parse(req.url).pathname

 

         var data=''

         if(pathname=='/test.js1'){data=callback+"(['','',''])"}

         else{data=callback+"(['one','two','three'])"}

 

         res.end(data)

         }

).listen(8081)





综合(数据的获取与方案的选择)

想加载这个资源到界面上,怎么做(这就是新浪微博的数据接口,赶紧去查新浪微博的API)//如果这个能自己解决了就可以自己去学后面jQuery了




1.请求的局部数据没有跨域(一般指自己公司的数据)

用AJAX请求数据

 

2.请求的局部数据如果跨域了

①去问后端(自己公司的后端,别人家公司的后端),让他告诉你(接口文档)JSONP请求的参数:回调函数名

比如百度搜索条的提示的JSONP接口:suggestion.baidu.com/su?wd=盖伦&cb=fn1

 

 

②有的公司给出了JSONP接口,有的没有给JSONP接口,比如我们一直没有解决的这个接口(其实是个移动端的请求接口)

这时候有两种解决方案:

one:老老实实去别人家公司的开发平台各种同意然后引入SDK

比如新浪微博API

 

two:还是用AJAX请求数据,请求自己服务器的数据! 数据由自己的服务器去请求(让后端的人写代码去请求,前端只管按照自己公司服务器逻辑去请求数据)

 

two的node代码:

var request = require('request');

request('https://api.weibo.com/2/statuses/home_timeline.json?access_token=2.00ZmCkcDTew45B578808a592mhaj_E',function (error, response, body) {

        if (!error&& response.statusCode == 200) {

           console.log(JSON.parse(body))//这里如果出数据了,说明我们自己公司的服务器有数据了,接下来就是自己去设计逻辑给前端发数据

        }

    })










原创粉丝点击