文章來源:小青年原創
發佈時間:2016-05-29
關鍵詞:mui,html5+,XMLHttpRequest,ajax,懶加載
轉載需標註本文原始地址: http://zhaomenghuan.github.io...javascript
這是這個系列的的第三篇文章,前面的文章在多個地方(本人github
博客、dcloud ask
社區、segmentfault
)發出來了,不少朋友收藏點贊,只是沒有多少人反映內容的深淺,也沒有人提出意見,因此實話說不知道符不符合你們胃口,不過我寫博客一貫以詳細爲標準,儘量照顧到各類人羣,特別是入門級的同窗,力求還原我學習這個東西的一個思路和過程,在文章中也分享一些不錯的乾貨,最近在折騰博客,用webpack
和vue-cli
打包了一下,目前還有些問題有待解決,本身嘗試寫一個markdown編輯器由於bug過多的問題,而後開始使用馬克飛象寫博客,畢竟生成的界面美觀多了,這樣能夠方便你們閱讀吧。廢話很少說,開始咱們今天的內容,今天主要是學習一下html5+
的XMLHttpRequest
以及mui
的基本用法。php
XMLHttpRequest 是一個 JavaScript 對象,它最初由微軟設計,隨後被 Mozilla、Apple 和 Google採納. 現在,該對象已經被 W3C組織標準化. 經過它,你能夠很容易的取回一個URL上的資源數據. 儘管名字裏有XML, 但 XMLHttpRequest 能夠取回全部類型的數據資源,並不侷限於XML。 並且除了HTTP ,它還支持file 和 ftp 協議. —— MDN XMLHttpRequestcss
XMLHttpRequest
讓發送一個HTTP
請求變得很是容易。你只須要簡單的建立一個請求對象實例,打開一個URL
,而後發送這個請求。當傳輸完畢後,結果的HTTP
狀態以及返回的響應內容也能夠從請求對象中獲取。html
第一步:建立一個 XMLHttpRequest 實例前端
new XMLHttpRequest();
第二步:初始化HTTP請求參數vue
void open( DOMString method, DOMString url, optional boolean async, optional DOMString user, optional DOMString password );
method:請求所使用的HTTP
方法; 例如 "GET"
, "POST"
, "PUT"
, "DELETE"
等. 若是下個參數是非HTTP(S)
的URL
,則忽略該參數.html5
url:該請求所要訪問的URL
java
async:一個可選的布爾值參數,默認爲true
,意味着是否執行異步操做,若是值爲false
,則send()
方法不會返回任何東西,直到接受到了服務器的返回數據。若是爲值爲true
,一個對開發者透明的通知會發送到相關的事件監聽者。這個值必須是true
,若是multipart
屬性是true
,不然將會出現一個意外。node
user:用戶名,可選參數,爲受權使用;默認參數爲空string
.jquery
password:密碼,可選參數,爲受權使用;默認參數爲空string
.
第三步:發送請求
send();
發送請求. 若是該請求是異步模式(默認),該方法會馬上返回. 相反,若是請求是同步模式,則直到請求的響應徹底接受之後,該方法纔會返回.
以下例:
var xhr = new XMLHttpRequest(); xhr.onload = function () { console.log(this.responseText); }; xhr.onreadystatechange = function() { console.log(this.readyState); }; xhr.open("get", "https://www.baidu.com", true); xhr.send();
咱們在hbuilder裏面打開,控制檯會報錯:
[Web瀏覽器] "XMLHttpRequest cannot load https://www.baidu.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8020' is therefore not allowed access."
用瀏覽器打開,按F12
在控制檯console
下查看也會發現上述錯誤,這是爲啥呢?
這是由於普通網頁可以使用XMLHttpRequest
對象發送或者接受服務器數據, 可是它們受限於同源策略。只要先獲取了跨域請求許可,就能夠進行跨域請求。
同源策略:若是兩個頁面的協議、域名和端口是徹底相同的,那麼它們就是同源的。同源策略是爲了防止從一個地址加載的文檔或腳本訪問或者設置從另一個地址加載的文檔的屬性。若是兩個頁面的主域名相同,則還能夠經過設置
document.domain
屬性將它們認爲是同源的。
CORS 的全稱是 Cross-Origin Resource Sharing,即跨域資源共享。他的原理就是使用自定義的 HTTP 頭部,讓服務器與瀏覽器進行溝通,主要是經過設置響應頭的 Access-Control-Allow-Origin 來達到目的的。這樣,XMLHttpRequest 就能跨域了。想要進一步瞭解CORS的朋友能夠看看這篇文章:瞭解跨域資源共享 (CORS)
在服務器端添加響應頭Access-Control-Allow-Origin
,使用XMLHttpRequest
對象請求。值得注意的是,正常狀況下的 XMLHttpRequest 是隻發送一次請求的,可是跨域問題下極可能是會發送兩次的請求(預發送)。
PHP:
header('Access-Control-Allow-Origin: *');
java:
response.addHeader( "Access-Control-Allow-Origin", "*" );
你們不妨將上面那個例子中的地址換成這個試試:http://zhaomenghuan.github.io...
(僅用於學習測試,禁止直接用於任何不經徵求本人贊成的站點)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> var xhr = new XMLHttpRequest(); xhr.open("get", "http://zhaomenghuan.github.io/api/blog.json", true); xhr.onload = function () { console.log(this.responseText); var data = JSON.parse(this.responseText); for(var i in data){ document.write(data[i].pageId + ':' + data[i].title+"<br />") } }; xhr.onerror = function () { alert('error making the request.'); }; xhr.send(); </script> </body> </html>
哈哈,執行完這段代碼你會發現,你可以查看到我博客的列表,因此你們是否是懂了些什麼, CORS可否跨域實現須要服務器端支持,咱們這裏可以收到信息,是由於github上的資源是支持CORS訪問的,這和框架無關,不少人覺得用了框架就能夠跨域,這都是不正確的理解,框架只是封裝了一些方法,讓咱們使用更加方便,能不能跨域仍是取決於咱們服務器端的訪問權限。這裏順便說一下不少人用mui會發如今瀏覽器端會報錯,在app環境可以訪問,這是由於mui依賴html5+ XMLHttpRequest網絡請求模塊,後面會詳細講到。
Jsonp
的跨域不是用XMLHttpRequest
實現的,而是一個script
標籤,script
是能夠跨域的,回調函數做爲get
參數傳入請求裏。
原理很簡單,好比你在A域名請求B域名:
在A域名的頁面中使用script標籤src寫成B域名中服務器的URLscript標籤是能夠跨域的,好比你調用Google Map或Google Analytics時引入的js就是google域名下的。
後端程序在最後須要把一段js代碼的字符串打印出來,這樣就能夠運行A域名js中寫好的callback方法,將要返回的數據放入參數就能夠了
A域名中的js文件:
function CreateScript(src){ var el = document.createElement('script'); el.src = src; el.async = true; el.defer = true; document.body.appendChild(el); } // 響應的方法 function jsonpcallback(rs) { console.log(JSON.stringify(rs)); document.getElementById("output").innerHTML = JSON.stringify(rs); } // 發起get請求 CreateScript('http://127.0.0.1:8888?userid=001&callback=jsonpcallback');
B域名中node服務器:
var http = require('http'); var url = require('url'); var data = { 'name': 'zhaomenghuan', 'age': '22' }; http.createServer(function(req, res){ // 將url字符串轉換成Url對象 var params = url.parse(req.url, true); console.log(params); // 查詢參數 if(params.query){ // 根據附件條件查詢 if(params.query.userid === '001'){ // 判斷是否爲jsonp方式請求,如果則使用jsonp方式,不然爲普通web方式 if (params.query.callback) { var resurlt = params.query.callback + '(' + JSON.stringify(data) + ')'; res.end(resurlt); } else { res.end(JSON.stringify(data)); } } } }).listen(8888);
這樣咱們就能夠在A域名下跨域請求,固然咱們常常看到不少框架如jquery對jsonp進行了進一步封裝,可是基本原理同上面。這裏給出兩個例子:
總之,不管是XMLHttpRequest
的跨域,仍是Jsonp
,都是須要請求的網站服務器端提供支持,在願意分享給你數據的狀況下你才能獲得。在對方沒有提供支持的狀況下,你是取不到它的數據的。固然跨域的解決方案有不少種,因爲本人沒有實踐過,沒有實踐就沒有發言權,這裏給你們貼一個帖子,本身跨域自行驗證,淺談瀏覽器端JavaScript跨域解決方法。
上面咱們花了很大篇幅講解了JavaScript XMLHttpRequest
對象,並且也簡單的講解了同源策略和跨域請求的經常使用方法,咱們注意到不管是JavaScript XMLHttpRequest
仍是jsonp
都須要經過服務器端的支持才能實現跨域,另外還有幾種也有必定的侷限性,因此總仍是讓人以爲美中不足。html5+
提供了一個XMLHttpRequest
模塊,在APP
端很完美的解決了這種問題,並且提供了和JavaScript XMLHttpRequest
對象用法相似的一系列屬性方法。因爲本文的重在在於講解html5+ XMLHttpRequest
,因此前面的JavaScript XMLHttpRequest
相關的屬性方法只是初略介紹了一下,下面重點介紹html5+ XMLHttpRequest
模塊。
因爲html5+ XMLHttpRequest
是一種拓展方案,因此須要底層支持,基於html5+ XMLHttpRequest
的方法不能用於非5+
環境,若是對這些概念不清楚的歡迎先閱讀我以前寫的文章mui初級入門教程(一)— 菜鳥入手mui的學習路線。
咱們用hbuilder
新建一個app工程,而後運行下面的代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title></title> </head> <body> <script type="text/javascript"> document.addEventListener('plusready', function(){ var xhr = new plus.net.XMLHttpRequest(); xhr.onreadystatechange = function () { switch ( xhr.readyState ) { case 0: console.log( "xhr請求已初始化" ); break; case 1: console.log( "xhr請求已打開" ); break; case 2: console.log( "xhr請求已發送" ); break; case 3: console.log( "xhr請求已響應"); break; case 4: if ( xhr.status == 200 ) { alert( "xhr請求成功:"+xhr.responseText ); } else { console.log( "xhr請求失敗:"+xhr.readyState ); } break; default : break; } } xhr.open("GET", "https://www.baidu.com/"); xhr.send(); }, false ); </script> </body> </html>
咱們會發現最後彈出了彈框,裏面寫有百度首頁的代碼。
建立一個XMLHttpRequest
對象,對象建立時不觸發任什麼時候間和網絡請求,需和open
,send
方法配合使用。
var xhr = new plus.net.XMLHttpRequest(); xhr.open(method, url); xhr.send();
XMLHttpRequest的屬性:
readyState: HTTP 請求的狀態
response: 請求從服務器接收到的響應數據
responseText: 請求從服務器接收到的響應數據(字符串數據)
responseType:請求響應數據response的類型
responseXML: 請求響應的Document對象
status: 服務器返回的HTTP狀態代碼
statusText: 服務器返回的HTTP狀態描述
timeout: 請求服務器的超時時間,單位爲毫秒(ms)
withCredentials: 是否支持跨域請求
XMLHttpRequest的方法:
abort: 取消當前響應,關閉鏈接而且結束任何未決的網絡活動
getAllResponseHeaders: 獲取HTTP響應頭部信息
getResponseHeader: 獲取指定的HTTP響應頭部的值
open: 初始化HTTP請求參數,例如URL和HTTP方法,可是並不發送請求
send: 發送HTTP請求
setRequestHeader: 指定一個HTTP請求的Header
XMLHttpRequest的事件:
onreadystatechange: 網絡請求狀態發生變化事件
onloadstart: 網絡請求開始事件
onprogress: 網絡請求傳輸數據事件
onabort: 網絡請求取消事件
onerror: 網絡請求錯誤事件
onload: 網絡請求成功事件
ontimeout: 網絡請求超時事件
onloadend: 網絡請求結束事件
mui
框架基於htm5plus
的XMLHttpRequest
,封裝了經常使用的Ajax
函數,支持GET
、POST
請求方式,支持返回json
、xml
、html
、text
、script
數據類型; 本着極簡的設計原則,mui
提供了mui.ajax
方法,並在mui.ajax
方法基礎上,進一步簡化出最經常使用的mui.get()
、mui.getJSON()
、mui.post()
三個方法。
mui.ajax( url [,settings] )
url:請求發送的目標地址
settings:key/value格式的json對象,用來配置ajax請求參數,支持的參數以下:
data:發送到服務器的業務數據;
type:請求方式,目前僅支持'GET'和'POST',默認爲'GET'方式;
dataType:預期服務器返回的數據類型;若是不指定,mui將自動根據HTTP包的MIME頭信息自動判斷;
支持設置的dataType可選值:
"xml": 返回XML文檔
"html": 返回純文本HTML信息;
"script": 返回純文本JavaScript代碼
"json": 返回JSON數據
"text": 返回純文本字符串
success:Type: Functon(Anything data,String textStatus,XMLHttpRequest xhr)
請求成功時觸發的回調函數,該函數接收三個參數:
data:服務器返回的響應數據,類型能夠是json對象、xml對象、字符串等;
textStatus:狀態描述,默認值爲'success'
xhr:xhr實例對象
error:Type: Functon(XMLHttpRequest xhr,String type,String errorThrown)請求失敗時觸發的回調函數;
該函數接收三個參數:
- xhr:xhr實例對象
- type:錯誤描述,可取值:"timeout", "error", "abort", "parsererror"、"null" - errorThrown:可捕獲的異常對象
timeout:Type: Number,請求超時時間(毫秒),默認值爲0,表示永不超時;若超過設置的超時時間(非0的狀況),依然未收到服務器響應,則觸發error回調;
headers:Type: Object,格式爲:{'Content-Type':'application/json'}
,
詳情參考html5+ setRequestHeader。
基本格式以下:
mui.ajax(url,{
data:{
username:'username', password:'password' }, dataType:'json',//服務器返回json格式數據 type:'post',//HTTP請求類型 timeout:10000,//超時時間設置爲10秒; success:function(data){ //服務器返回響應,根據響應結果,分析是否登陸成功; ... }, error:function(xhr,type,errorThrown){ //異常處理; console.log(type); } });
mui.post( url [,data] [,success] [,dataType] )
mui.post()
方法是對mui.ajax()
的一個簡化方法,直接使用POST
請求方式向服務器發送數據、且不處理timeout
和異常(若需處理異常及超時,請使用mui.ajax()
方法)
mui.post('http://server-name/login.php',{ username:'username', password:'password' },function(data){ //服務器返回響應,根據響應結果,分析是否登陸成功; ... },'json' );
mui.get( url [,data] [,success] [,dataType] )
mui.get()
方法和mui.post()
方法相似,只不過是直接使用GET
請求方式向服務器發送數據、且不處理timeout
和異常(若需處理異常及超時,請使用mui.ajax()
方法)。以下爲得到某服務器新聞列表的代碼片斷,服務器以json格式返回數據列表:
mui.get('http://server-name/list.php', {category:'news'}, function(data){ //得到服務器響應 ... },'json' );
mui.get( url [,data] [,success] )
mui.getJSON()
方法是在mui.get()
方法基礎上的更進一步簡化,限定返回json
格式的數據,其它參數和mui.get()
方法一致,如上得到新聞列表的代碼換成mui.getJSON()
方法後,更爲簡潔,以下:
mui.getJSON('http://server-name/list.php', {category:'news'}, function(data){ //得到服務器響應 ... } );
mui在getJSON基礎上封裝了一個jsonp插件,具體dem能夠參考這裏:mui-jsonp實現有道詞典翻譯
注:初學者肯對於GET與POST的區別不是很清楚,這裏不作詳細介紹,若要深刻了解請查看:GET,POST — 簡述
咱們接着上一篇文章的項目開始進行本節的內容,上一篇咱們講解了html5+ webview
的使用方法,而且實現了一個基於父子webview
的tab bar
切換的案例,咱們此次利用網易音樂API
接口請求數據,完成咱們後續的音樂播放器功能。
網易音樂搜索API:
type:"GET"或「POST" //HTTP請求類型
請求參數:
type: 1
s: //關鍵詞
limit: 10 //限制返回結果數爲10
offset: 0 //偏移
src: lofter //可爲空
filterDj: true | false //可爲空
callback: //爲空時返回json,反之返回jsonp callback
因爲HTTP請求類型包含get,咱們只須要把請求的參數拼接到url裏面就能夠獲得返回的數據,格式爲url?key1=value1&key2=value2。
在這個例子中咱們打開這個網址http://s.music.163.com/search...,咱們會發現一些數據返回了,以下圖:
OK,咱們下面講解怎麼經過程序獲得這些數據,而且咱們而且怎麼解析這些數據。
在開始以前咱們先對咱們要獲得的數據進行美化,這裏我在網上隨便搜了一個
在線JSON校驗格式化工具,咱們只須要把剛剛那些數據複製粘貼到我給的這個工具裏面,而後點擊校驗就變整齊了。
{
"result": { "songCount": 3224, "songs": [ { "id": 28949444, "name": "喜歡你", "artists": [ { "id": 7763, "name": "G.E.M.鄧紫棋", "picUrl": null } ], "album": { "id": 2956076, "name": "喜歡你", "artist": { "id": 0, "name": "", "picUrl": null }, "picUrl": "http://p1.music.126.net/u_1EudmF8Swgow6vfgYe1g==/8896148580676276.jpg" }, "audio": "http://m2.music.126.net/_icR1apQHVl8wa0EP_REkQ==/3269947581061892.mp3", "djProgramId": 0 } ] }, "code": 200 }
咱們能夠看到
"picUrl":"http://p1.music.126.net/u_1EudmF8Swgow6vfgYe1g==/8896148580676276.jpg"
打開這個圖片地址咱們就能夠看到鄧紫棋了,哈哈,也就是說咱們只須要抓取到這個地址就能夠進行下面的工做咯,其餘的相似。
咱們在上次新建的M-BOX下的home.html下寫這個例子:
<script src="../js/mui.min.js"></script> <script type="text/javascript"> var url = "http://s.music.163.com/search/get/"; mui.ajax(url,{ data: { 'type': 1, 's': "喜歡你", 'limit': 10 }, dataType:'json',//服務器返回json格式數據 type:'post',//HTTP請求類型 timeout:10000,//超時時間設置爲10秒; success:function(data){ console.log(JSON.stringify(data)); }, error:function(xhr,type,errorThrown){ //異常處理; console.log(type); } }); </script>
hbuilder
很方便的一個功能就是真機調試,咱們直接將電腦與手機鏈接,經過console.log()
函數能夠很方便的將數據在控制檯打印出來,例如上述例子若是咱們在success
的回調函數中執行console.log(data);
,在控制檯會輸出[object Object]
,咱們只須要利用JSON.stringify()
方法能夠將任意的 JavaScript
值序列化成 JSON
字符串。
每次看到不少同窗在解析json
的時候錯誤百出,嚴重暴漏了基本功,這裏我就總結幾條與解析json
可能相關的知識點。
JSON: JavaScript Object Notation
(JavaScript 對象表示法),JSON
是存儲和交換文本信息的語法,獨立於語言。相似 XML
。JSON
比 XML
更小、更快,更易解析,具備自我描述性,更易理解的特色。
JSON
就是一串字符串,只不過元素會使用特定的符號標註。
{} 雙括號表示對象
[] 中括號表示數組
"" 雙引號內是屬性或值
:表示後者是前者的值(這個值能夠是字符串、數字、也能夠是另外一個數組或對象)
{"name": "Dcloud"}
能夠理解爲是一個包含name
爲Dcloud
的對象;[{"name": "mui"},{"name": "html5+"}]
就表示包含兩個對象的數組。
經過JavaScript
,您能夠建立一個對象數組,並像這樣進行賦值:
var employees = [ { "firstName":"John" , "lastName":"Doe" }, { "firstName":"Anna" , "lastName":"Smith" }, { "firstName":"Peter" , "lastName": "Jones" } ];
能夠像這樣訪問 JavaScript 對象數組中的第一項:employees[0].lastName;
返回的內容是:Doe
能夠像這樣修改數據:employees[0].firstName = "Jonatan";
這裏須要特別說明的是兩個很是有用的方法:JSON.stringify和JSON.parse。咱們能夠經過JSON.stringify將json對象轉成json字符串,方便用alert,console.log打印出來,能夠方便的查看json對象內容。反之咱們能夠經過JSON.parse將json字符串轉成json對象以即可以方便對json對象取值。例:
// 場景1 var data = { name: 'zhaomenghuan', age: 22 } console.log(typeof data); // "object" console.log(JSON.stringify(data)) // "{"name":"zhaomenghuan","age":22}" // 場景2 var str = '{"name":"zhaomenghuan","age":22}'; console.log(typeof str) // "string" console.log(JSON.parse(str).name) // "zhaomenghuan"
上面的例子列舉了兩種應用場景,你們根據本身的狀況合適的選取正確的方法。
[ ]能夠用於數組和對象取值,數組中按下邊取值。
var array=["one","two","three","four"]; array[0];
對象屬性取值時,當咱們不知道屬性名或屬性名自己包含點(.)的鍵,應當使用[ ]。
for(var key in obj){ console.log(key + ":" + obj[key]); }
var obj={ id:"obj", "self.ref":ref } console.log(obj["self.ref"]);
.運算符的左邊爲一個對象,右邊爲屬性名。如:obj.id
var key="property"; console.log(key); var obj={ property:"hello word" } console.log(obj[key]);
var array=[1,2,3,4,5]; array.map(function(item){ return item*2; });
數組map
方法能夠接受一個匿名函數,數組中每一個元素都會調用這個匿名函數,而且講返回結果放在一個數組中。
mui
中的each()
方法既是一個類方法,同時也是一個對象方法,兩個方法適用場景不一樣;換言之,你可使用mui.each()
去遍歷數組或json
對象,也可使用mui(selector).each()
去遍歷DOM
結構。
mui.each( obj , handler )
obj :Type: Array||JSONObj
需遍歷的對象或數組;若爲對象,僅遍歷對象根節點下的key
handler :Type: Function( Integer||String index,Anything element)
爲每一個元素執行的回調函數;其中,index表示當前元素的下標或key,element表示當前匹配元素
對於前面說到的音樂api
返回的json
數據,首先咱們要經過var songs=data.result.songs;
獲取"songs"
的值,而後遍歷"songs"
對象的子對象。
···
success:function(data){ // console.log(JSON.stringify(data)); var songs=data.result.songs; mui.each(songs,function(index,item){ var id = item.id, name = item.album.name, author = item.artists[0].name, picUrl = item.album.picUrl, audio = item.audio; }) }, ···
咱們用上述代碼能夠獲得咱們想要的數據,下面就是須要將信息展現出來,這裏咱們只獲取 歌曲id
、歌曲所屬專輯名name
、歌曲第一做者author
、歌曲所屬專輯圖片picUrl
、歌曲音頻文件audio
。
考慮到要加載不少圖片,這裏咱們使用懶加載實現效果,這裏咱們直接使用hello mui
裏面的模板頁面lazyload-image.html
,咱們須要引入mui.lazyload.js
和mui.lazyload.img.js
兩個文件,還有佔位圖。下面先貼出修改後的基本的代碼,而後再講解其中的內容。
home.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>M-BOX</title> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <!--標準mui.css--> <link rel="stylesheet" href="../css/mui.min.css"> <style type="text/css"> .mui-content>.mui-table-view:first-child { margin-top: 0px; } </style> </head> <body> <div class="mui-content"> <ul id="list" class="mui-table-view mui-table-view-chevron"></ul> </div> </body> <script src="../js/mui.min.js "></script> <script src="../js/mui.lazyload.js"></script> <script src="../js/mui.lazyload.img.js"></script> <script> mui.init(); var url = "http://s.music.163.com/search/get/"; mui.ajax(url,{ data: { 'type': 1, 's': "喜歡你", 'limit': 10 }, dataType:'json',//服務器返回json格式數據 type:'post',//HTTP請求類型 timeout:10000,//超時時間設置爲10秒; success:function(data){ //console.log(JSON.stringify(data)); var songs=data.result.songs; var list = document.getElementById("list"); var fragment = document.createDocumentFragment(); var li; mui.each(songs,function(index,item){ var id = item.id, name = item.album.name, author = item.artists[0].name, picUrl = item.album.picUrl, audio = item.audio; li = document.createElement('li'); li.className = 'mui-table-view-cell mui-media'; li.innerHTML = '<a class="mui-navigate-right" id='+ id +' data-audio='+ audio +'>'+ '<img class="mui-media-object mui-pull-left" data-lazyload="'+picUrl+'">'+ '<div class="mui-media-body">'+name+ '<p class="mui-ellipsis">'+author+'</p>'+ '</div>'+ '</a>'; fragment.appendChild(li); }) list.appendChild(fragment) mui(document).imageLazyload({ placeholder: '../img/60x60.gif' }); }, error:function(xhr,type,errorThrown){ //異常處理; console.log(type); } }); //列表點擊事件 mui("#list").on('tap','li a',function(){ var id = this.getAttribute('id'); var audio = this.getAttribute('data-audio'); //打開詳情頁面 mui.openWindow({ url:'music.html', id:'music.html', extras:{ musicId:id, audioUrl:audio } }); }); </script> </html>
music.html:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title></title> <link href="../css/mui.min.css" rel="stylesheet"/> </head> <body> <script src="../js/mui.min.js"></script> <script type="text/javascript"> mui.init(); mui.plusReady(function(){ var self = plus.webview.currentWebview(); var musicId = self.musicId; var audioUrl = self.audioUrl; document.write("musicId:" + musicId + "<br />"); document.write("audioUrl:" + audioUrl); }); </script> </body> </html>
咱們這裏說幾個開發者常見的問題:
首先打開hello mui
裏面的模板頁面lazyload-image.html
,咱們打開控制檯查看elements
,結構以下:
<ul id="list" class="mui-table-view mui-table-view-chevron"> <li class="mui-table-view-cell mui-media"> <a class="mui-navigate-right"> <img class="mui-media-object mui-pull-left" data-lazyload-id="0" src="http://www.dcloud.io/hellomui/images/1.jpg?version=447.4190210457891"> <div class="mui-media-body"> 主標題 <p class="mui-ellipsis">列表二級標題</p> </div> </a> </li> </ul>
咱們須要將獲取的內容動態的填充到這個裏面,這裏經常使用的方法就是動態的生成節點,這裏咱們就要用到DOM
的建立方法document.createElement
,經過這個方法咱們能夠生成一個節點: li = document.createElement('li');
這個能夠生成一個li
節點,咱們須要爲這個li
指定class
,經過對對象的className
賦值實現,如:li.className = 'mui-table-view-cell mui-media';
,咱們使用appendChild(li)
方法將li
節點掛着父節點上,好比:
var list = document.getElementById("list"); list.appendChild(li);
這個就是把li
節點掛在list
下,同理咱們能夠在li
節點下 建立子節點,上面爲了簡單,咱們使用給innerHTML
屬性賦值的作法,這樣innerHTML
的值一樣會掛在li
節點下,你們須要注意的是innerHTML
屬性的值我字符串,因此咱們往中間插入了變量,要使用+
鏈接起來。咱們能夠經過循環建立多個節點,以下面這樣建立十個段落:
for(var i = 0 ; i < 10; i ++) { var p = document.createElement("p"); var oTxt = document.createTextNode("段落" + i); p.appendChild(oTxt); document.body.appendChild(p); }
上面咱們使用的是mui.each()
方法,效果相似。
若是細心的同窗或許注意到咱們使用了一個奇怪的寫法:
var fragment = document.createDocumentFragment(); mui.each(songs,function(index,item){ ... fragment.appendChild(li); }); list.appendChild(fragment);
爲啥咱們要在這裏使用document.createDocumentFragment()
呢?
若是是對前端技術感興趣的同窗說不定回去查一下,我相信大部分人可能就放過了吧!這裏我查了一下資料:
在《javascript高級程序設計》一書的6.3.5:建立和操做節點一節中,介紹了幾種動態建立html節點的方法,其中有如下幾種常見方法:
crateAttribute(name): 用指定名稱name建立特性節點
createComment(text): 建立帶文本text的註釋節點
createDocumentFragment(): 建立文檔碎片節點
createElement(tagname): 建立標籤名爲tagname的節點
createTextNode(text): 建立包含文本text的文本節點
其中最感興趣且之前沒有接觸過的一個方法是createDocumentFragment()方法,書中介紹說:在更新少許節點的時候能夠直接向document.body節點中添加,可是當要向document中添加大量數據是,若是直接添加這些新節點,這個過程很是緩慢,由於每添加一個節點都會調用父節點的appendChild()方法,爲了解決這個問題,能夠建立一個文檔碎片,把全部的新節點附加其上,而後把文檔碎片一次性添加到document中。—— document的createDocumentFragment()方法
咱們點擊了列表,咱們會進入一個詳情頁,咱們確定是想知道咱們究竟點了哪個咱們想把一些數據傳入到詳情頁面,這裏咱們使用了mui.openWindow()
方法中的拓展參數extras
傳入幾個值,在詳情頁面經過plus.webview.currentWebview
獲取:
mui.plusReady(function(){ var self = plus.webview.currentWebview(); var musicId = self.musicId; var audioUrl = self.audioUrl; document.write("musicId:" + musicId + "<br />"); document.write("audioUrl:" + audioUrl); });
這是在頁面初始化時,經過擴展參數extras
傳值;另外還有頁面已建立,經過自定義事件傳值,參考mui官網中自定義事件的介紹,這裏先不講得太多,後面會專門花時間詳細講解相關細節。
因爲前面已經詳細講解,這裏就再也不贅述,只給出一個基本的demo:jsonp獲取網易雲音樂。
當咱們寫到這裏,發現這篇依然是長長的一篇乾貨,不少內容摘自文檔,主要是爲了新手能夠詳細去了解整個流程。其實還有不少沒有寫出來,限於篇幅仍是後面再寫吧!因爲代碼在文章中寫得很詳細,工程代碼先不給出來,最後整個系列寫完了再放出來吧!
這段時間在技術上花得時間確實太多,剛剛和女友在圖書館學習,她和我開個玩笑,我在忙着作做業由於不喜歡被打擾,而後就以爲很煩躁,而後就聊着聊着她說和我分手,我不知道她是否是認真的,只是以爲空空的,自從走上代碼這條路,我已經失去太多東西,我不想失去女友,畢竟談了三年,我是真的愛她,寫完這個就去找她道歉吧!還有要向環頭道歉,昨天可能說話有點直接,不當心傷到他了,後來想一想真的多是我太較真,他只是想玩玩程序,我何須那種執着呢?若是環頭看到這篇博客,但願你能夠原諒哥,我只是不想讓你走彎路,或許每一個都應該本身去把握本身的人生,咱們沒必要去幹涉。