Js_Dom(9)__Dom基礎

什麼是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.οnlοad=function(){

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

btn.οnclick=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.οnclick=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").οnclick=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").οnclick=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").οnclick=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").οnclick=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’).οnclick=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.οnclick=function(){

         varscript1=document.createElement("script")

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

         document.body.appendChild(script1)

         }

btn2.οnclick=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.οnclick=function(){

         varscript1=document.createElement("script")

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

         document.body.appendChild(script1)

         }

btn2.οnclick=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))//這裏如果出數據了,說明我們自己公司的服務器有數據了,接下來就是自己去設計邏輯給前端發數據

        }

    })










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章