一、初識jQuery.js
jQuery.js是一款優(yōu)秀的JS類庫,其本質(zhì)就是在一個立即執(zhí)行的匿名函數(shù)中的閉包,jQuery=js+Query(查詢),從命名可以看出jQuery.js最主要的用途是用來做查詢,在jQuery.js官方Logo下方還有一個副標(biāo)題(write less, do more),體現(xiàn)了jQuery.js除了查詢以外,還可以實現(xiàn)強(qiáng)大選擇器(即方便快速查找DOM元素,jQuery.js允許開發(fā)者使用CSS1-CSS3幾乎所有的選擇器,以及jQuery.js獨(dú)創(chuàng)的選擇器),鏈?zhǔn)秸{(diào)用(即可以通過“.”不斷的調(diào)用jQuery.js中的各種方法),隱式遍歷/迭代(即一次操作多個DOM元素),讀寫合一(即讀數(shù)據(jù)和寫數(shù)據(jù)使用同一個jQuery方法),事件處理,DOM操作(即C增U改D刪),樣式操作,動畫,豐富的插件支持,Ajax變得更加簡單,瀏覽器兼容(即解決前端開發(fā)者痛點),1.x版本兼容ie678,但相對其它版本文件較大,官方只做BUG維護(hù),功能不再新增,最終版本是1.12.4(2016年5月20日),2.x版本不兼容ie678,相對1.x文件較小,官方只做BUG維護(hù),功能不再新增,最終版本是2.2.4(2016年5月20日),3.x版本不兼容ie678,只支持最新的web瀏覽器,不支持很多老的jQuery.js插件,相對1.x文件較小,而且3.x提供不包含Ajax/動畫API的版本,我們通過查看百度、騰訊、和京東的網(wǎng)頁源代碼,發(fā)現(xiàn)使用的都是1.x版本,所以我們學(xué)習(xí)1.x版本就可以了,開發(fā)版的意思是所有的源代碼沒有經(jīng)過壓縮,所以體積更大(200-300KB),生產(chǎn)版的意思是所有的源代碼經(jīng)過了壓縮,所以體積更?。?0-40KB),為了初學(xué)者更好的理解jQuery.js,當(dāng)開發(fā)時,我們使用開發(fā)版,當(dāng)項目上線時,為了提升訪問速度,我們再換成生產(chǎn)版即可,首先上官網(wǎng)“jquery.com”下載jQuery.js類庫,然后在我們自己的.html文件引入所下載的jQuery.js類庫,最后編寫jQuery代碼即可,原生JS入口函數(shù)的固定寫法是“window.onload = function () {可執(zhí)行的代碼;};”,當(dāng)寫了多個原生JS的入口函數(shù)時,先編寫的會被后編寫的所覆蓋,由于原生JS的入口函數(shù)會等到此頁面上的img加載完畢再執(zhí)行,所以當(dāng)此頁面上的一個<img>沒有設(shè)置寬高時,利用原生JS的入口函數(shù)可以獲取到此<img>的寬高,jQuery.js入口函數(shù)的固定寫法是“$ (document).ready (function () {可執(zhí)行的代碼;} );”/“jQuery (document).ready (function () {可執(zhí)行的代碼;} );”/“$ (function () {可執(zhí)行的代碼;} );(//推薦)”/“jQuery (function () {可執(zhí)行的代碼;} );”,當(dāng)寫了多個jQuery.js的入口函數(shù)時,先編寫的不會被后編寫的所覆蓋,由于jQuery.js的入口函數(shù)不會等到此頁面上的img加載完畢再執(zhí)行,所以當(dāng)此頁面上的一個<img>沒有設(shè)置寬高時,利用jQuery.js的入口函數(shù)無法獲取到此<img>的寬高,當(dāng)引入了多個類庫/框架,并且其它類庫/框架也有$符號時,$符號的使用勢必就會有沖突,所以我們可以釋放jQuery代碼中$符號的使用權(quán),在編寫其它jQuery代碼之前寫上一句“jQuery.noConflict ();”即可,釋放之后就不能再使用$符號了,可以改為使用jQuery,還可以自定義一個符號來代替jQuery,例如“var nj = jQuery.noConflict ();(//從此nj就代替了jQuery的功能)”
二、jQuery.js中的核心函數(shù)和工具方法
$就代表jQuery這個類庫名,只不過簡寫為$,“$ ();”就等同于“jQuery ();”,代表調(diào)用jQuery.js的核心函數(shù),在調(diào)用的時候可以向里邊傳參,可以傳入一個回調(diào)函數(shù),即入口函數(shù),格式為“$ (function () {可執(zhí)行的代碼;});”,可以傳入一個空字符串/null/undefined/NaN/0/false,返回值是一個空的jQuery集合,可以傳入一個基本數(shù)據(jù)/對象/DOM元素,返回值是一個保存了所傳入的基本數(shù)據(jù)/對象/DOM元素的jQuery集合,例如“$ (oSpan);”,可以傳入一個選擇器字符串,例如“$ (“.box1”);(//返回值是一個保存了在此頁面上所找到的傳入選擇器字符串所指代的所有DOM元素的jQuery集合)”,可以傳入一個HTML代碼片段字符串,例如“$ (“<p>我是段落</p>”);(//返回值是一個保存了傳入HTML代碼片段字符串所指代的新createElement的DOM元素的jQuery集合,當(dāng)所傳入的HTML代碼片段存在嵌套關(guān)系時,只有一級DOM元素會保存在jQuery集合中)”,可以傳入一個真/偽數(shù)組,返回值是一個保存了所傳入的真/偽數(shù)組中所有元素的jQuery集合,含有0、1、2、...一直到(length-1)的屬性以及l(fā)ength屬性的對象就叫做偽數(shù)組(或者叫偽數(shù)組對象),jQuery集合其實就是一個偽數(shù)組,原生JS中的forEach和map等方法是無法遍歷偽數(shù)組的,jQuery集合調(diào)用它的get方法可以返回此集合中第傳入索引個元素(當(dāng)不傳參時,就相當(dāng)于調(diào)用toArray方法,當(dāng)傳入一個負(fù)數(shù)時,就相當(dāng)于用此數(shù)值與此集合的總長度值相加),jQuery的DOM元素集合調(diào)用它的index方法可以返回此集合中的首個DOM元素在其同級別標(biāo)簽中的索引值,jQuery集合調(diào)用它的each方法可以遍歷此集合,返回值是調(diào)用者,在所傳入回調(diào)函數(shù)的作用域中,this指針指代的是所遍歷到的元素,“return true;”就相當(dāng)于“continue;”,“return false;”就相當(dāng)于“break;”,jQuery類對象調(diào)用它的each方法可以遍歷參數(shù)1真/偽數(shù)組/對象,返回值是參數(shù)1,在參數(shù)2回調(diào)函數(shù)的作用域中,this指針指代的是所遍歷到的元素,“return true;”就相當(dāng)于“continue;”,“return false;”就相當(dāng)于“break;”,例如“var arr = [1, 3, 5, 7, 9]; ?var obj = {0: 1, 1: 3, 2: 5, 3: 7, 4: 9, length: 5}; ?$.each (obj, function (index, value) {console.log(index, value);} );(//第一個形參index接收到的實參是所遍歷到的索引值,第二個形參value接收到的實參是所遍歷到的元素,只能接收到這倆參數(shù))”,jQuery類對象調(diào)用它的map方法可以遍歷參數(shù)1真/偽數(shù)組,返回值是參數(shù)2回調(diào)函數(shù)的返回值所組成的數(shù)組,例如“$.map (obj, function (value, index) {return value + index;});(//返回值是[1, 4, 7, 10, 13])”,jQuery類對象調(diào)用它的trim方法可以返回傳入字符串被去除兩端空格之后的新字符串,例如“var str = “l(fā)nj ??”; ?$.trim (str);(//返回值是“l(fā)nj”)”,jQuery類對象調(diào)用它的isWindow方法可以判斷所傳入的數(shù)據(jù)是否是window對象,返回值是true/false,jQuery類對象調(diào)用它的isArray方法可以判斷所傳入的數(shù)據(jù)是否是真數(shù)組,返回值是true/false,jQuery類對象調(diào)用它的isFunction方法可以判斷所傳入的數(shù)據(jù)是否是一個函數(shù),返回值是true/false,jQuery類對象調(diào)用它的holdReady方法可以暫停/恢復(fù)ready事件,傳入true代表暫停,傳入false代表恢復(fù),例如“$.holdReady (true); ?$ (document).ready (function () {alert (“ready”);} );(//不會有彈窗)”,jQuery集合調(diào)用它的toArray方法可以返回此集合被轉(zhuǎn)成的真數(shù)組
三、jQuery.js中的選擇器以及操作html網(wǎng)頁的各種相關(guān)方法
jQuery.js中的內(nèi)容選擇器有“:empty”、“:parent”、“:contains()”、和“:has()”,“:empty”的作用是選中沒有任何內(nèi)容(文本/子標(biāo)簽)的冒號前的標(biāo)簽,例如“var $div = $ (“div:empty”);”,“:parent”的作用是選中含有內(nèi)容(文本/子標(biāo)簽)的冒號前的標(biāo)簽,例如“var $div = $ (“div:parent”);”,“:contains()”的作用是選中包含小括號內(nèi)文本內(nèi)容的冒號前的標(biāo)簽,例如“var $div = $ (“div:contains(‘我是div’)”);”,“:has()”的作用是選中包含小括號內(nèi)子標(biāo)簽的冒號前的標(biāo)簽,例如“var $div = $ (“div:has(‘span’)”);”,一個對象身上所保存的變量就叫做屬性,在JS中,HTML標(biāo)簽的HTML屬性就叫做屬性節(jié)點,任何對象都有屬性,但是只有DOM元素才有屬性節(jié)點,在瀏覽器的開發(fā)者工具(F12)中,點擊Sources->右側(cè)的Watch->上面的加號,然后輸入例如“document.querySelector (“.one”);”,找到相應(yīng)DOM元素后,展開之后所看到的都是屬性,在attributes偽數(shù)組中所保存的所有元素都是屬性節(jié)點,我們可以調(diào)用原生JS中的setAttribute和getAttribute方法來操作屬性節(jié)點,jQuery的DOM元素集合調(diào)用它的attr方法可以返回/修改/批量修改此集合中首個/所有DOM元素的傳入系統(tǒng)自帶/自定義屬性節(jié)點字符串的取值(在傳入跟取值相同的屬性節(jié)點字符串時,如checked/selected/disabled屬性節(jié)點,當(dāng)調(diào)用者添加了所傳入的屬性節(jié)點時,返回值是此屬性節(jié)點字符串,當(dāng)沒添加時,返回值是undefined,不推薦,碰到此種情況建議改用prop方法,其余情況用attr方法即可),返回值是調(diào)用者,例如“console.log ($ (“span”).attr (“class”) );(//首個span元素)”,“$ (“span”).attr (“class”, “box”);(//所有span元素,沒有就新增)”,“$ (“span”).attr ({class: “a123”, name: “888”});(//所有span元素,沒有就批量新增)”,jQuery的DOM元素集合調(diào)用它的prop方法可以返回/修改/批量修改此集合中首個/所有DOM元素的傳入屬性/系統(tǒng)自帶屬性節(jié)點字符串的取值(在傳入了跟取值相同的屬性節(jié)點字符串時,如checked/selected/disabled屬性節(jié)點,當(dāng)調(diào)用者添加了所傳入的屬性節(jié)點時,返回值是true,當(dāng)沒添加時,返回值是false,官方推薦),返回值是調(diào)用者,例如“console.log ($ (“p”).prop (“title”) );(//首個p元素,當(dāng)傳入一個自定義的屬性節(jié)點字符串時,返回值是undefined)”,“$ (“p”).prop (“demo”, “l(fā)nj”);(//所有p元素,沒有就新增)”,“$ (“p”).prop ({class: “a123”, name: “888”});(//所有p元素,沒有就批量新增)”,jQuery的DOM元素集合調(diào)用它的removeProp/removeAttr方法可以刪除此集合中所有DOM元素所傳入的屬性/屬性節(jié)點字符串,例如“$ (“span”).removeAttr (“class name”);(//有多個就用空格隔開)”,jQuery的DOM元素集合調(diào)用它的addClass/removeClass/toggleClass方法可以給此集合中所有DOM元素添加/刪除一/多個所傳入的類名字符串/切換addClass和removeClass的狀態(tài),返回值是調(diào)用者,當(dāng)調(diào)用者擁有所傳入的類名時,addClass方法不會重復(fù)去添加,當(dāng)不傳參時,removeClass和toggleClass方法會刪除調(diào)用者所有的類名,例如“$ (“div”).addClass (“class1 class2”);”,jQuery的DOM元素集合調(diào)用它的html/text方法既可以返回此集合中首個/所有DOM元素內(nèi)部包含/不包含兩端空格和HTML標(biāo)簽的內(nèi)容字符串,也可以將此集合中所有DOM元素中的內(nèi)容設(shè)置為所傳入的包含HTML標(biāo)簽/普通(即出現(xiàn)HTML標(biāo)簽時會當(dāng)成普通的字符串)的字符串(html方法也可以傳入一個jQuery的DOM元素集合/DOM元素),例如“$ (“div”).html ($ (“p”) );(//會將此頁面上的p元素剪切,并設(shè)置為div元素中的內(nèi)容)”,jQuery的input輸入框元素集合調(diào)用它的val方法可以返回/設(shè)置此集合中首個/所有單行文本輸入框中所輸入的內(nèi)容字符串,返回值是調(diào)用者,jQuery的DOM元素集合調(diào)用它的prepend/append方法可以在此集合中所有DOM元素內(nèi)部的最前/后面添加所傳入的HTML代碼片段字符串/jQuery的DOM元素集合/DOM元素/文本內(nèi)容,返回值是調(diào)用者,jQuery的DOM元素集合調(diào)用它的prependTo/appendTo方法可以將此集合中所有DOM元素添加到傳入選擇器字符串/jQuery的DOM元素集合/DOM元素內(nèi)部的最前/后面,返回值是調(diào)用者,例如“$ (“<li>新增的li</li>”).appendTo (“ul”);”,jQuery的DOM元素集合調(diào)用它的before/after方法可以在此集合中所有DOM元素的前/后面都添加所傳入的HTML代碼片段字符串/jQuery的DOM元素集合/DOM元素/文本內(nèi)容,jQuery的DOM元素集合調(diào)用它的insertBefore/insertAfter方法可以將此集合中所有DOM元素添加到傳入選擇器字符串/jQuery的DOM元素集合的前/后面,返回值是調(diào)用者,例如“$ (“<div>你好</div>”).insertAfter (“ul”);”,jQuery的DOM元素集合調(diào)用它的remove/detach方法可以刪除此集合中傳入選擇器字符串所指代的DOM元素,當(dāng)不傳參時,會刪除此集合中的所有DOM元素,返回值是調(diào)用者(remove跟detach的不同是,remove還會將被刪除DOM元素所綁定的事件以及所附加的數(shù)據(jù)也一并移除),jQuery的DOM元素集合調(diào)用它的empty方法可以刪除此集合中所有DOM元素中的所有內(nèi)容,返回值是調(diào)用者,jQuery的DOM元素集合調(diào)用它的replaceWith方法可以將此集合中所有DOM元素替換為所傳入的HTML代碼片段字符串/jQuery的DOM元素集合/DOM元素,例如“$ (“div”).replaceWith ($ (“p”) );(//將此頁面上的p元素剪切,并將div元素替換掉)”,jQuery的DOM元素集合調(diào)用它的replaceAll方法可以將所傳入的選擇器字符串所指代的DOM元素替換為此集合中所有的DOM元素,例如“$ (“<h6>我是標(biāo)題6</h6>”).replaceAll (“h1”);”,jQuery的DOM元素集合調(diào)用它的clone方法可以返回深/淺復(fù)制的此調(diào)用者,傳入true/false是深/淺復(fù)制,淺復(fù)制只會復(fù)制此調(diào)用者,而深復(fù)制除了會復(fù)制此調(diào)用者,還會復(fù)制其所綁定的事件,jQuery的DOM元素集合調(diào)用它的css方法可以返回/設(shè)置此集合中首個/所有DOM元素傳入的行內(nèi)樣式/CSS屬性字符串的取值,返回值是調(diào)用者,例如“console.log ($ (“div”).css (“backgroundColor”) );(//首個div元素)”,“$ (“div”).css (“width”, “100px”);(//所有div元素,當(dāng)設(shè)置時,設(shè)置成的一定是行內(nèi)樣式)”,“$ (“div”).css (“width”, “100px”).css (“height”, “100px”).css (“backgroundColor”, “blue”);(//所有div元素,鏈?zhǔn)皆O(shè)置,當(dāng)鏈?zhǔn)讲僮鞔笥?步時,建議分開寫,否則閱讀性較差)”,“$ (“div”).css ({width: “100px”, height: “100px”, backgroundColor: “red”});(//所有div元素,批量設(shè)置,當(dāng)CSS屬性名稱帶有中劃線時,要改成駝峰命名)”,jQuery的DOM元素集合調(diào)用它的width/height方法可以返回/設(shè)置此集合中所有DOM元素width/height屬性的取值,例如“$ (“.father”).width ();(//返回值不帶單位px)”,“$ (“.father”).width (“500px”);”,jQuery的DOM元素集合調(diào)用它的offset方法可以返回/設(shè)置此集合中首個DOM元素的左和上邊緣與網(wǎng)頁可視區(qū)域的左和上邊緣的距離值對象(包含left和top兩個屬性),例如“$ (“.son”).offset ().left;(//返回值不帶單位px)”,“$ (“.son”).offset ({left: 10});(//傳入對象中屬性的取值不能帶單位px)”,jQuery絕對/固定定位標(biāo)簽偽數(shù)組對象調(diào)用它的position方法可以返回(但無法設(shè)置)此集合中首個DOM元素的左和上邊緣與其最近的定位流上級元素的左和上邊緣的距離值對象(包含left和top兩個屬性),例如“$ (“.son”).position ().left;(//返回值不帶單位px)”,jQuery的DOM元素/html/body元素集合調(diào)用它的scrollLeft/scrollTop方法可以返回/設(shè)置此集合中所有DOM元素/此網(wǎng)頁橫/豎向滾動條滾出的距離值,例如“$ (“.scroll”).scrollTop (300);”,“console.log ($ (“body”).scrollTop () + $ (“html”).scrollTop () );(//為了做兼容性處理,因為IE瀏覽器支持$ (“body”),非IE瀏覽器支持$ (“html”))”,“$ (“html, body”).scrollTop (300);(//為了做兼容性處理)”,jQuery集合調(diào)用它的eq方法可以返回一個只有此集合中第傳入索引個元素的jQuery集合(當(dāng)不傳參時,返回值是一個空的jQuery集合,當(dāng)傳入負(fù)數(shù)時,就相當(dāng)于用此數(shù)值與總長度值相加),例如“$ (“span”).eq (0);”,jQuery的DOM元素集合調(diào)用它的first方法可以返回一個只有此集合中首個DOM元素的jQuery集合,jQuery的DOM元素集合調(diào)用它的last方法可以返回一個只有此集合中最后一個DOM元素的jQuery集合,jQuery的DOM元素集合調(diào)用它的siblings方法可以返回一個跟此集合中所有DOM元素同級別的其它DOM元素所組成的jQuery集合(一般用來做排它),jQuery的DOM元素集合調(diào)用它的children方法可以返回一個此集合中所有DOM元素的傳入選擇器字符串所指代的子代DOM元素所組成的jQuery集合(當(dāng)不傳參時,返回值是一個所有子代DOM元素所組成的jQuery集合),例如“$ (“.nav>li”).children (“.sub”);”,jQuery的DOM元素集合調(diào)用它的parents/find方法可以返回一個此集合中所有DOM元素的傳入選擇器字符串所指代的上/下級DOM元素所組成的jQuery集合,例如“$ (“.infoDel”).parents (“.info”);”,jQuery的DOM元素集合調(diào)用它的hasClass方法可以檢測此集合中所有DOM元素是否含有所傳入的類名字符串,返回值是true/false,當(dāng)未傳參時,返回值是false,jQuery的DOM元素集合調(diào)用它的prev/next方法可以返回一個此集合中所有DOM元素緊鄰的上/下一個同級別DOM元素所組成的jQuery集合
四、jQuery.js中事件的綁定
jQuery.js中有兩種綁定事件方式,第一種方式是利用jQuery的DOM元素集合調(diào)用它的去掉on的事件名稱來綁定,然后傳入一個回調(diào)函數(shù)即可,例如“$ (“button”).click (function () {alert (“hello lnj”);} );”,優(yōu)點是在調(diào)用去掉on的事件名稱的時候編輯器會給予提示,所以編碼效率略高,還不容易寫錯,缺點是部分JS事件在jQuery.js中沒有實現(xiàn),所以不能綁定,第二種方式是利用jQuery的DOM元素集合調(diào)用它的on方法來綁定,然后傳入?yún)?shù)1去掉on的事件名稱字符串和參數(shù)2回調(diào)函數(shù)即可,例如“$ (“button”).on (“click”, function () {alert (“hello click1”);} );”,優(yōu)點是所有的JS事件都可以綁定,缺點是事件名稱是以字符串的形式傳入,編輯器不會給予提示,所以編碼效率略低,還容易寫錯,以上這兩種綁定方式都會給此jQuery的DOM元素集合所包含的所有DOM元素都綁定上相應(yīng)事件,返回值是調(diào)用者,所傳入回調(diào)函數(shù)的作用域中的this指針指代的是觸發(fā)此事件的DOM元素,當(dāng)使用這兩種綁定方式給某個jQuery的DOM元素集合綁定多個同名事件時,不會發(fā)生覆蓋,并且觸發(fā)的順序是正向的,由于mouseover/mouseout事件無法阻止事件冒泡,所以在一個同時綁定了mouseover和mouseout事件的jQuery的DOM元素集合中,當(dāng)鼠標(biāo)從此集合所包含的DOM元素mouseover到其子代DOM元素時,會先觸發(fā)其mouseout事件,后觸發(fā)其mouseover事件(冒泡所導(dǎo)致),當(dāng)再從其子代DOM元素mouseover到此DOM元素時,會先觸發(fā)其mouseout事件(冒泡所導(dǎo)致),后觸發(fā)其mouseover事件,而mouseenter/mouseleave事件則可以阻止事件冒泡(推薦),給jQuery的DOM元素集合所綁定的hover事件的觸發(fā)條件是鼠標(biāo)移入/出此集合所包含的DOM元素(可傳入一/兩個回調(diào)函數(shù)),例如“$ (“.father”).hover (function () {console.log (“father被移入了”);}, function () {console.log (“father被移出了”);} );”,“$ (“.father”).hover (function () {console.log (“father被移入移出了”);} );”,給jQuery的window對象集合所綁定的scroll事件的觸發(fā)條件是此瀏覽器窗口的滾動條發(fā)生滾動,給jQuery的input輸入框/textarea/select元素集合所綁定的change事件的觸發(fā)條件是此集合所包含的單/多行文本輸入框中的內(nèi)容發(fā)生改變并失去焦點(只有手動輸入的才有效)/在此集合所包含的下拉菜單中選擇了某個選項,由于change事件失去焦點才能觸發(fā),所以當(dāng)想要實時監(jiān)聽單/多行文本輸入框中的內(nèi)容是否發(fā)生改變時,就不能使用change事件了,而且必須用使用事件委托,固定寫法是例如“$ (“body”).delegate (“.comment”, “propertychange input”, function () {});(//為了做兼容性處理,所以綁定了propertychange和input兩個事件)”,jQuery的DOM元素集合調(diào)用它的off方法可以移除給此集合中所有DOM元素所綁定的所傳入的事件名稱字符串,例如“$ (“button”).off ();(//不傳參會移除所綁定的所有事件)”,“$ (“button”).off (“click”);”,“$ (“button”).off (“click”, function () {alert (“button”);} );(//參數(shù)2為參數(shù)1事件的回調(diào)函數(shù),當(dāng)給調(diào)用者綁定了多個同名的參數(shù)1事件時,可以定向移除某一個參數(shù)1事件)”,在jQuery中,阻止事件冒泡的方式是在傳入的回調(diào)函數(shù)作用域的結(jié)尾處添加一句“return false;”/“event.stopPropagation ();(//需用形參event接收一下事件對象)”,讓手動綁定的事件覆蓋掉跟系統(tǒng)同名的事件(即阻止默認(rèn)行為/移除默認(rèn)事件)的方式是在傳入的回調(diào)函數(shù)作用域的結(jié)尾處添加一句“return false;”/“event.preventDefault ();(//需用形參event接收一下事件對象)”,jQuery的DOM元素集合調(diào)用它的trigger/triggerHandler方法可以自動觸發(fā)此集合中所有DOM元素所綁定的所傳入的事件名稱字符串,trigger方法會觸發(fā)事件冒泡和默認(rèn)事件,而triggerHandler方法則不會,例如“$ (“.son”).trigger (“click”);”,但是a元素比較特殊,即使調(diào)用了trigger方法也無法觸發(fā)其默認(rèn)事件,解決方式是在a元素內(nèi)部再嵌套一個span元素,將a元素中的內(nèi)容包起來,然后利用jQuery的span元素集合調(diào)用它的trigger方法并傳入相應(yīng)事件名稱字符串即可,例如“$ (“span”).trigger (“click”);”,當(dāng)想要自定義事件名稱時,必須滿足兩個條件,一是此事件必須是調(diào)用on方法來綁定的,二是此事件必須調(diào)用trigger/triggerHandler方法來自動觸發(fā),例如“$ (“.son”).on (“myClick”, function () {alert (“son”);} ); ?$ (“.son”).trigger (“myClick”);”,jQuery的DOM元素集合調(diào)用它的on方法來給其綁定多個同名事件時,是存在事件命名空間的(即可以分別給此同名事件添加不同的備注名稱),并且也可以調(diào)用trigger/triggerHandler方法來自動觸發(fā)其中一個,例如“$ (“.son”).on (“click.zs”, function () {alert (“click1”);} ); ?$ (“.son”).on (“click.ls”, function () {alert (“click2”);} ); ?$ (“.son”).trigger (“click.ls”);”,當(dāng)調(diào)用trigger方法自動觸發(fā)某個DOM元素帶有命名空間的事件時,其父DOM元素帶有相同命名空間的同名事件也會被自動觸發(fā)(冒泡),而其父DOM元素不帶有相同命名空間的同名事件則不會被自動觸發(fā),當(dāng)調(diào)用trigger方法自動觸發(fā)某個DOM元素不帶有命名空間的事件時,此DOM元素和其父DOM元素所有的同名事件都會被自動觸發(fā),在jQuery中,DOM元素可以將某個事件委托給其父DOM元素來監(jiān)聽,jQuery上級DOM元素集合調(diào)用它的delegate方法可以使參數(shù)1選擇器字符串所指代的下級DOM元素委托此上級DOM元素來監(jiān)聽參數(shù)2事件字符串,觸發(fā)后執(zhí)行參數(shù)3回調(diào)函數(shù)(但無法監(jiān)聽hover事件,只能使用mouseenter和mouseleave事件來代替),適用于監(jiān)聽后期使用JS代碼所動態(tài)添加的DOM元素,因為在入口函數(shù)執(zhí)行的時候,此頁面上的某些DOM元素就已經(jīng)存在了,例如“$ (“ul”).delegate (“l(fā)i”, “click”, function () {console.log ($ (this).html () );} );(//由于delegate方法的底層原理是event.target,所以click事件其實是綁定給了ul元素,這里的this指針指的是觸發(fā)click事件的那個li元素,也就是將click事件冒泡給ul元素的那個li元素)”,jQuery的DOM元素集合調(diào)用它的one方法可以給此集合中所有DOM元素綁定只能觸發(fā)一次的事件,例如“$ (“.wolfImage”).one (“click”, function () {});”
五、jQuery.js中的transition和animation
jQuery的DOM元素集合調(diào)用它的show/hide/toggle方法可以給此集合中所有DOM元素的display屬性設(shè)置transition并設(shè)置display值為auto/none/切換show和hide的狀態(tài),例如“$ (“div”).show (1000, “l(fā)inear”, function () {alert (“顯示的transition執(zhí)行完畢”);} );(//參數(shù)1毫秒值代表transition執(zhí)行的時長,也可以換成“slow”/“normal”/“fast”,參數(shù)2為可選參數(shù),代表transition執(zhí)行的節(jié)奏,默認(rèn)為“swing”,慢快慢,參數(shù)3回調(diào)函數(shù)在transition執(zhí)行完畢后執(zhí)行)”,jQuery的DOM元素集合調(diào)用它的slideDown/slideUp/slideToggle方法可以給此集合中所有DOM元素的display和height屬性設(shè)置transition并設(shè)置它倆的值為auto和其本來的值/none和0/切換slideDown和slideUp的狀態(tài),用法同上,jQuery的DOM元素集合調(diào)用它的stop方法可以立即停止此集合中所有DOM元素當(dāng)前的transition,并繼續(xù)執(zhí)行后續(xù)的transition(不傳參/傳入一/兩個false),也可以立即停止當(dāng)前和后續(xù)的transition(傳入一個true/一個true一個false),也可以立即完成當(dāng)前的transition,并繼續(xù)執(zhí)行后續(xù)的transition(傳入一個false一個true),還可以立即完成當(dāng)前的transition,并停止后續(xù)的transition(傳入兩個true),由于jQuery的transition中存在隊列,即只有前一個transition執(zhí)行完畢,后一個transition才會執(zhí)行,所以當(dāng)想要停掉上一個未完成的transition時,在執(zhí)行當(dāng)前這個transition之前調(diào)用一下stop方法即可(推薦),例如“$ (.sub).stop ();”,jQuery的DOM元素集合調(diào)用它的fadeIn/fadeTo/fadeOut/fadeToggle方法可以給此集合中所有DOM元素的display和opacity屬性設(shè)置transition并設(shè)置它倆的值為auto和其本來的值/auto和所傳入的值/none和0/切換fadeIn和fadeOut的狀態(tài),例如“$ (“div”).fadeTo (1000, 0.2, “l(fā)inear”, function () {alert (“淡入到0.2完畢”);} )(//0.2代表opacity值)”,“$ (“.ad”).stop ().slideDown (1000).fadeOut (1000).fadeIn (1000);(//由于存在transition隊列,所以我們可以通過鏈?zhǔn)秸{(diào)用來設(shè)置多個transition,事先stop一下只是為了規(guī)避一些隱含的bug,不影響效果)”,jQuery的DOM元素集合調(diào)用它的animate方法可以給此集合中所有DOM元素的一/多個行內(nèi)樣式屬性設(shè)置animation(當(dāng)設(shè)置多個時,多個行內(nèi)樣式屬性的animation會同時執(zhí)行),例如“$ (“.two”).animate ({width: 500}, 1000, “l(fā)inear”, function () {alert (“自定義animation執(zhí)行完畢”);} );(//參數(shù)1也可傳入比如“{width: “+=100”}(//意思是在原基礎(chǔ)上加100)”/“{width: “hide”/“show”/“toggle”}”)”,jQuery的DOM元素集合調(diào)用它的delay方法可以讓此集合中所有DOM元素延遲傳入的毫秒值再執(zhí)行之后的animation,例如“$ (“.one”).animate ({width: 500}, 1000).delay (2000).animate ({height: 500}, 1000);”,jQuery.fx對象修改它的off屬性值可以關(guān)閉此頁面上所有的animation,格式為“jQuery.fx.off = true;(//默認(rèn)值是false)”,jQuery.fx對象修改它的interval屬性值可以設(shè)置此頁面上animation的顯示幀速,例如“jQuery.fx.interval = 100;(//默認(rèn)值是13,值越大越卡,越小越流暢,也越消耗瀏覽器的性能)”
六、mCustomScrollbar.js插件
此插件是一個基于jQuery.js的插件,可以美化滾動條的樣式,先上官網(wǎng)manos.malihu.gr/jquery-custom-content-scroller,找到download,下載到本地并解壓縮,引入文件的順序為jquery.mCustomScrollbar.css、自己的index.css(因為在我們自己的index.css中有可能去操作jquery.mCustomScrollbar.css)、jQuery.js、jquery.mCustomScrollbar.concat.min.js、自己的index.js,然后找到頁面上的“Initialization”標(biāo)題,直接調(diào)用它封裝好的函數(shù)就可以了,例如“$ (“.content”).mCustomScrollbar ();(//“.content”代表某個DOM元素)”,然后找到“Initialize via HTML”標(biāo)題,就可以看到在HTML結(jié)構(gòu)代碼上如何使用了,找到想美化的那個HTML標(biāo)簽,給它添加一個自定義的HTML屬性,叫做data-mcs-theme屬性,取值有很多可以選擇,找到頁面上的“view demo”標(biāo)題,點擊“Scrollbar themes”按鈕,就可以看到不同的取值分別代表不同的樣式,當(dāng)想要修改滾動條的寬度時,可以閱讀主頁上的“Scrollbar markup”標(biāo)題下的內(nèi)容,當(dāng)想要把滾動條的寬度改為8px時,需要在我們自己的index.css上添加上一句“._mCS_1 .mCSB_dragger .mCSB_dragger_bar {width: 8px;}”即可,由于在國內(nèi)用此插件的人比較多,所以網(wǎng)上也有很多中文的文檔,可以自己百度一下中文的文檔
七、jQuery.js的原理
jQuery的本質(zhì)是一個閉包,即定義在一個立即執(zhí)行的匿名函數(shù)內(nèi)部的子函數(shù),好處是當(dāng)引入多個類庫/框架時,可以避免這些類庫/框架中所定義變量的命名沖突,在此立即執(zhí)行的匿名函數(shù)的作用域中,必須通過“window.jQuery?= jQuery;”的方式將此局部jQuery函數(shù)轉(zhuǎn)成全局函數(shù),jQuery函數(shù)所在的立即執(zhí)行的匿名函數(shù)之所以給自己傳入一個window對象一是為了方便后期壓縮代碼,因為形參就可以用一個字母例如“w”來代替了,二是為了提升查找的效率,因為當(dāng)自己的作用域中有window對象時,使用自己作用域中的就可以了,就不用沿著作用域鏈去查找了,jQuery函數(shù)所在的立即執(zhí)行的匿名函數(shù)之所以要用形參給自己接收一個undefined,一是為了方便后期壓縮代碼,二是為了保證內(nèi)部使用的undefined不被修改,因為在IE9以下的低級瀏覽器中,undefined是可以被修改的,例如“undefined = 998;(//在IE9以下的低級瀏覽器中,undefined就變成了998)”,所以需要接收一個正確的undefined,jQuery的精髓是免用new,直接“jQuery ();”就可以return一個init函數(shù)(類)的實例對象,但是為了使此實例對象可以調(diào)用jQuery.prototype中所定義的各種方法,必須在最后加上一句“jQuery.prototype.init.prototype = jQuery.prototype;(//將init類的prototype對象指向了jQuery類的prototype對象)”,這樣一來,我們所獲取到的實例對象就可以調(diào)用jQuery.prototype中所定義的各種方法了
八、AJAX
“器”這個詞在硬件領(lǐng)域指的是一個看得見、摸得著的實物,在軟件領(lǐng)域指的是“程序”,同理,服務(wù)器在硬件領(lǐng)域指的是一臺24小時不斷電、不關(guān)機(jī),并且提供了某種服務(wù)功能的超級電腦,而在軟件領(lǐng)域指的是提供了某種服務(wù)功能的程序,根據(jù)所提供服務(wù)的不同又分為文件服務(wù)器、郵件服務(wù)器、和web服務(wù)器(例如Apache、IIS、Tomcat、Nginx、和NodeJS)等,所以,提供管理網(wǎng)站服務(wù)的軟件/安裝了此軟件的電腦都可以叫做web服務(wù)器,WAMPServer指的就是W(Windows操作系統(tǒng))+A(Apache,世界排名第一的web服務(wù)器,特點是簡單、速度快、性能穩(wěn)定)+M(MySQL數(shù)據(jù)庫,一款開源免費(fèi)的數(shù)據(jù)庫軟件,特點是體積小、速度快、使用成本低)+P(php解釋器,php即Personal home page Hypertext Preprocessor,就是個人主頁超文本預(yù)處理程序,可以直接將代碼嵌入HTML文檔中執(zhí)行,特點是簡單易學(xué),容易上手),安裝Apache的方法是,先雙擊WAMPServer安裝包,然后選擇語言,只有English,沒有Chinese,點擊OK->Next->Next,選擇安裝路徑(路徑中一定不要出現(xiàn)中文,否則以后會有一些未知的bug,比如系統(tǒng)托盤區(qū)的圖標(biāo)不變綠),然后點擊Next->Next,點擊install開始安裝,然后點擊“是”選擇瀏覽器,任意一個瀏覽器都可以,比如找到桌面,選擇谷歌瀏覽器,點擊“打開”,再點“是”,再找到桌面,再選擇谷歌瀏覽器,再點擊“打開”,然后點擊Next->Finish安裝完畢,然后雙擊打開WAMPServer,在系統(tǒng)托盤區(qū)會出現(xiàn)一個圖標(biāo),此圖標(biāo)一開始是紅色的,然后變?yōu)辄S色的,最后會變?yōu)榫G色的,只有它變?yōu)榫G色的才代表著此軟件正常的運(yùn)行了,此電腦就可以提供web相關(guān)的服務(wù)了(即變成了一臺本地web服務(wù)器),可以測試訪問一下,打開web瀏覽器,訪問web服務(wù)器默認(rèn)的ip地址“127.0.0.1”,就看到顯示的內(nèi)容了,由于php是服務(wù)端編程語言,所以php代碼只能使用php解釋器配合web服務(wù)器(例如Apache)來解釋執(zhí)行,當(dāng)我們經(jīng)由webstorm使用web瀏覽器來打開.php文件時,雖然webstorm默認(rèn)就是服務(wù)端的環(huán)境,但是也是無法解釋執(zhí)行php代碼的,頁面會報“502 bad gateway”的錯誤,所以我們必須先雙擊運(yùn)行WAMPServer軟件,然后將.php文件放在WAMPServer軟件安裝目錄中名叫“www”的文件夾中,然后再使用web瀏覽器訪問web服務(wù)器的ip地址(即向web服務(wù)器發(fā)送請求報文),但是默認(rèn)打開的是“www”文件夾中的“index.php”文件,當(dāng)將此文件更改一下名稱時,再次使用web瀏覽器訪問web服務(wù)器的ip地址,就默認(rèn)進(jìn)入“www”文件夾了,然后從此文件夾的目錄中就可以找到我們放進(jìn)去的那個.php文件了,找到之后一點擊就打開了,就可以將此.php文件中php代碼的執(zhí)行結(jié)果(即所輸出的數(shù)據(jù))渲染出來了,.php文件的名稱不能有中文,php的代碼都需要寫在“<?php”和“?>”之間,“?>”可寫可不寫,php的大部分基礎(chǔ)語法跟JS的差不多,php中的注釋跟JS中的注釋長得一模一樣,功能也一模一樣,php中定義變量的格式為“$變量名 = 取值;”,輸出(返回)變量的格式為“echo $變量名;”,php中也可以定義集合,即數(shù)組/字典(對象),定義數(shù)組的格式為“$arr = array (1, 3, 5);”,輸出(返回)數(shù)組的格式為“print_r ($arr);”,輸出(返回)數(shù)組中某個元素的格式為“echo $arr[1];”,定義字典(對象)的格式為“$dict = array (“name”=> “l(fā)nj”, “age”=> “33”);”,輸出(返回)字典(對象)的格式為“print_r ($dict);”,輸出(返回)字典(對象)中某個元素的格式為“echo $dict[“name”];”,php中的分支循環(huán)語句跟JS中的也類似,例如“if ($age >= 18) {echo “成年人”;} else {echo “未成年人”;}”,“$res = ($age >= 18) ? “成年人”: “未成年人”;”,“switch ($age) {case -1: echo “非人類”; ?break; ?case 18: echo “成年人”; ?break; ?default: echo “未成年人”; ?break;}”,“$arr = array (1, 3, 5); ?for ($i = 0; $i < count ($arr); $i++) {echo $arr[$i]; ?echo “<br>”;}”,“$index = 0; ?while ($index < count ($arr) ) {echo $arr[$index]; ?echo “<br>”; ?$index++;}”,php中有超全局變量$_GET、$_POST、和$_FILES,前兩個分別用來接收web瀏覽器通過get和post請求所提交過來的數(shù)據(jù)(文件除外),第三個是用來接收web瀏覽器所提交過來的文件(例如.jpg/.mp4文件),一定注意文件/文件夾的名稱不能出現(xiàn)中文,否則會亂碼/報錯,因為web服務(wù)器不支持中文,然后web服務(wù)器會默認(rèn)將所接收到的文件保存到安裝目錄的tmp文件夾(臨時文件夾),當(dāng)保存了一會之后仍然未使用時,就會自動刪除,以節(jié)約web服務(wù)器的存儲空間,超全局變量中所保存的數(shù)據(jù)都是字典(對象),$_FILES字典訪問它的upFile屬性可以返回上傳文件所對應(yīng)的字典,upFile字典訪問它的name屬性可以返回上傳文件的名稱字符串,upFile字典訪問它的tmp_name屬性可以返回上傳文件被保存的臨時路徑字符串,調(diào)用move_uploaded_file函數(shù)可以將參數(shù)1所上傳的文件名稱字符串移動到參數(shù)2新路徑字符串,例如“move_uploaded_file ($filePath, “./source/”.$fileName);(//在php中用“.”來拼接字符串)”,調(diào)用sleep函數(shù)可以停留傳入的秒數(shù)值再執(zhí)行后面的代碼,例如“sleep (5);”,調(diào)用file_get_contents函數(shù)可以返回傳入的文件URL字符串中此文件中的數(shù)據(jù)字符串,例如“file_get_contents (“info.xml”);(//當(dāng)所返回的數(shù)據(jù)中有中文時,可能會出現(xiàn)亂碼問題,只需要在php文件頂部添加上一句“header (“content-type:text/html; charset=utf-8”);(//html也可以換成xml)”即可,當(dāng)所返回的是JSON時,就不用添加了)”,調(diào)用json_encode函數(shù)可以返回傳入字典被轉(zhuǎn)成的JSON,當(dāng)此函數(shù)執(zhí)行失敗時,返回值是false,使用web瀏覽器訪問html網(wǎng)頁的過程是首先根據(jù)在web瀏覽器地址欄所輸入的URL向web服務(wù)器發(fā)送請求報文,web服務(wù)器(例如Apache)接收到之后會先對請求報文進(jìn)行處理,然后再將html文件通過響應(yīng)報文返回給web瀏覽器,最后web瀏覽器再將所返回的html文件渲染出來即可,向web服務(wù)器發(fā)送請求與提交數(shù)據(jù)(即與web服務(wù)器交互)的過程也是首先根據(jù)web瀏覽器地址欄的URL/請求頭中所保存的內(nèi)容,向web服務(wù)器發(fā)送請求報文,web服務(wù)器(例如Apache)接收到之后會先對請求報文進(jìn)行處理,然后再在此web服務(wù)器上執(zhí)行經(jīng)過解釋器所解釋后的服務(wù)端代碼(例如php代碼),然后再將此代碼的執(zhí)行結(jié)果(即所輸出的數(shù)據(jù))通過響應(yīng)報文返回給web瀏覽器,最后web瀏覽器再將所輸出的數(shù)據(jù)渲染出來即可,默認(rèn)情況下web服務(wù)器對需要上傳的文件是有限制的,當(dāng)想要修改此限制時,可以修改“php.ini”文件,路徑是WAMPServer安裝目錄->bin->apache->apache2.4.23->bin->php.ini,找到之后最好用編輯器打開,不要用記事本,容易產(chǎn)生編碼問題,可以搜索以下幾項做一下更改,file_uploads = On,是否允許web瀏覽器上傳文件,取值是On/Off,默認(rèn)值是On,upload_max_filesize = 2M,web瀏覽器上傳文件的最大限制,可以改成2048M,post_max_size = 8M,允許web瀏覽器通過post請求所提交的最大數(shù)據(jù),可以改成2048M,max_execution_time = 120,web服務(wù)器上腳本最長的執(zhí)行時間,單位為秒,可以改成3000,max_input_time = 60,web服務(wù)器接收所提交數(shù)據(jù)的時間限制,單位為秒,可以改成3000,memory_limit = 128M,允許web服務(wù)器最大的內(nèi)存消耗,可以改成2048M,全都修改完之后保存一下,然后重啟一下WAMPServer,只需要單擊系統(tǒng)托盤區(qū)的此軟件圖標(biāo),然后單擊“Restart All Services”就可以了,AJAX(Asynchronous JavaScript and XML)即異步的JS和XML,并不是一門新的編程語言,而是在不重新加載整個html頁面的情況下與web服務(wù)器交換數(shù)據(jù)并更新部分html頁面的技術(shù),使用AJAX總共分為五步,第一步new一個AJAX異步對象(XMLHttpRequest對象/ActiveXObject對象),XMLHttpRequest對象兼容除了IE5和IE6之外的所有瀏覽器,IE5和IE6使用ActiveXObject對象,例如“var xmlhttp; ?if (window.XMLHttpRequest) {xmlhttp = new XMLHttpRequest ();} else {xmlhttp = new ActiveXObject (“Microsoft.XMLHTTP”);}”,第二步設(shè)置向web服務(wù)器提交數(shù)據(jù)的請求方式和URL,例如“xmlhttp.open (“get”, “04-ajax-get.php?userName=zs&userPwd=321”, true);(//參數(shù)1傳入請求的類型字符串,大小寫均可,參數(shù)2傳入請求的url字符串,即文件在web服務(wù)器的路徑字符串,參數(shù)3傳入true/false,表示異步/同步,由于AJAX存在的意義就是發(fā)送異步請求,所以參數(shù)3永遠(yuǎn)傳true)”,當(dāng)需要發(fā)送的是post請求時,需要再寫一句“xmlhttp.setRequestHeader (“Content-type”, “application/x-www-form-urlencoded”);(//設(shè)置請求頭)”,第三步是發(fā)送請求,例如“xmlhttp.send ();(//get請求,不用傳參,因為在第二步時會將需要提交的數(shù)據(jù)附加到URL后面的“?”后面)”,“xmlhttp.send (“userName=zs&userPwd=321”);(//post請求)”,異步對象調(diào)用它的abort方法可以中斷請求,例如“xmlhttp.abort ();”,第四步是監(jiān)聽異步對象請求狀態(tài)碼的變化,給異步對象所綁定的onreadystatechange事件的觸發(fā)條件是此異步對象的readyState值發(fā)生了改變,異步對象訪問它的readyState屬性可以返回此異步對象的請求狀態(tài)碼(數(shù)值),0代表請求未初始化,1代表跟web服務(wù)器的連接已建立,2代表web服務(wù)器已接收到請求,3代表web服務(wù)器正在處理請求,4代表web服務(wù)器已將請求處理完畢,且響應(yīng)已就緒,異步對象訪問它的status屬性可以返回web服務(wù)器的響應(yīng)狀態(tài)碼(數(shù)值),只要此響應(yīng)狀態(tài)碼是大于等于200且小于300或者是304(304代表返回本地的緩存數(shù)據(jù))就代表響應(yīng)成功,除此之外的響應(yīng)狀態(tài)碼就代表響應(yīng)失敗,當(dāng)所請求的url不存在時,就會響應(yīng)失敗,例如“xmlhttp.onreadystatechange = function () {if (xmlhttp.readyState === 4) {if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status === 304) {console.log (“獲取到web服務(wù)器所輸出的數(shù)據(jù)”);} else {console.log (“沒有獲取到web服務(wù)器所輸出的數(shù)據(jù)”);} } }”,第五步是處理web服務(wù)器所輸出的數(shù)據(jù),就是執(zhí)行觸發(fā)onreadystatechange事件之后的回調(diào)函數(shù),異步對象訪問它的responseText屬性可以返回web服務(wù)器所輸出的數(shù)據(jù)字符串(非XML時使用),所返回的數(shù)據(jù)會隨著web服務(wù)器所輸出數(shù)據(jù)的變化而變化,但在IE瀏覽器中,由于IE瀏覽器會緩存通過get請求從web服務(wù)器所獲取到的內(nèi)容,所以在通過AJAX發(fā)送get請求時,當(dāng)所請求的URL沒有發(fā)生變化時,IE瀏覽器就不會再次向web服務(wù)器發(fā)送get請求,而是直接從IE瀏覽器的緩存中返回上次通過該URL從web服務(wù)器所獲取到的數(shù)據(jù),這樣一來,無論怎么修改web服務(wù)器所輸出的數(shù)據(jù),IE瀏覽器都會將首次所獲取到的結(jié)果直接返回,不會返回web服務(wù)器所輸出的最新數(shù)據(jù),從而導(dǎo)致數(shù)據(jù)的不同步,當(dāng)想要返回web服務(wù)器所輸出的實時變化的數(shù)據(jù)時,必須保證每一次發(fā)送get請求時URL都有變化,我們可以在URL后面附加上比如“?t=一個隨機(jī)數(shù)(隨機(jī)因子)”,這樣一來,web服務(wù)器不會做任何處理,并且可以返回web服務(wù)器所輸出的最新數(shù)據(jù),隨機(jī)數(shù)可以使用“Math.random ();”/“new Date ().getTime ();”,例如“xmlhttp.open (“GET”, “05-ajax-get.txt?t=”+ (new Date ().getTime () ), true);”,異步對象訪問它的responseXML屬性可以返回web服務(wù)器所輸出的XML文檔對象(即document對象,所返回的此document對象可以訪問/調(diào)用JS中相應(yīng)的屬性/方法來返回相應(yīng)的數(shù)據(jù)),例如“xmlhttp.responseXML.querySelector (“age”).innerHTML;”,XML(Extensible Markup Language)是可擴(kuò)展標(biāo)記語言,XML文件是有固定格式的,第一行必須寫上“<?xml version=“1.0”encoding=“UTF-8”?>”,version值是XML的版本號,encoding值是XML的字符集,一般情況下字符集都是UTF-8,第一行寫完之后,還必須有一對根標(biāo)簽,只不過XML的根標(biāo)簽可以隨意命名,例如“<abc></abc>”,所有數(shù)據(jù)都必須嵌套在這對根標(biāo)簽中才有效,而這對根標(biāo)簽中的每一條數(shù)據(jù)也都是需要嵌套在一對隨意命名的雙標(biāo)簽中的,jQuery類對象調(diào)用它的ajax方法可以通過HTTP請求來獲取web服務(wù)器所輸出的數(shù)據(jù),格式為“$.ajax ({配置對象});”,在配置對象中可以添加url屬性,取值是需要發(fā)送請求的URL字符串,可以添加timeout屬性,取值是毫秒值,當(dāng)請求時長超過此毫秒值時,就中斷請求,可以添加type屬性,取值是“get”(默認(rèn)值)/“post”,可以添加data屬性,取值是一個對象/字符串(例如“userName=lnj&userPwd=123456”),當(dāng)取值是一個對象時,會自動轉(zhuǎn)成字符串,當(dāng)取值是一個對象并且value是一個數(shù)組時,例如“{foo: [“bar1”, “bar2”]}”,會轉(zhuǎn)成“&foo=bar1&foo=bar2”,當(dāng)需要發(fā)送的是get請求時,會自動將此data值附加在此url值之后,可以添加dataType屬性,取值是“xml”/“html”/“script”/“json”/“jsonp”/“text”,可以添加jsonp屬性,取值是在一個jsonp請求中,用來取代URL后面所附加的“callback=隨機(jī)函數(shù)名”中的callback部分的自定義名稱字符串,可以添加jsonpCallback屬性,取值是在一個jsonp請求中,用來取代URL后面所附加的“callback=隨機(jī)函數(shù)名”中的隨機(jī)函數(shù)名部分的自定義名稱字符串,可以添加complete方法,取值是在請求完成后無論響應(yīng)成功/失敗都會執(zhí)行的回調(diào)函數(shù)“function (XMLHttpRequest, textStatus) {}”,形參textStatus接收到的是描述成功請求類型的字符串,可以添加success方法,取值是在請求完成并響應(yīng)成功后所執(zhí)行的回調(diào)函數(shù)“function (data, textStatus) {}”,形參data接收到的是web服務(wù)器所輸出的根據(jù)配置對象中的dataType值進(jìn)行處理后的數(shù)據(jù),可以添加error方法,取值是在請求完成但響應(yīng)失敗后所執(zhí)行的回調(diào)函數(shù)“function (XMLHttpRequest) {}”,會話跟蹤技術(shù)分為web瀏覽器的和web服務(wù)器的,web瀏覽器的是cookie,web服務(wù)器的是session,由于web前端屬于web瀏覽器端,所以我們只需要了解cookie就可以了,cookie是此html網(wǎng)頁保存到此web瀏覽器中的數(shù)據(jù)(key-value格式的文本信息),web瀏覽器默認(rèn)不會保存任何的cookie,也不能一次性保存多條cookie,當(dāng)想要保存多條cookie時,只能一條一條的設(shè)置,cookie有大小和條數(shù)的限制,根據(jù)web瀏覽器的不同,條數(shù)通常限制在20條到50條左右,為了兼容所有web瀏覽器,一般情況下我們不會設(shè)置超過20條,總大小限制在4KB左右,并且每次都會攜帶在HTTP頭中發(fā)送到web服務(wù)器,所以當(dāng)使用cookie保存過多的數(shù)據(jù)時,就會帶來性能問題,cookie經(jīng)常用于存儲用戶的登錄狀態(tài),由于會把用戶的登錄狀態(tài)發(fā)送到web服務(wù)器,所以在本地驗證完,在web服務(wù)器可以進(jìn)一步的驗證,這樣就達(dá)到了雙重驗證的效果,谷歌瀏覽器不支持JS在本地操作cookie(火狐支持),只有在web服務(wù)器的環(huán)境下才可以操作cookie,document對象訪問它的cookie屬性可以返回/設(shè)置此web瀏覽器中所保存的cookie,例如“document.cookie = “age=33;”;”,設(shè)置完之后,我們可以通過F12(開發(fā)者工具)->Application->Cookies,點擊展開,然后再點擊此網(wǎng)址來查看,web瀏覽器中所保存cookie的生命周期默認(rèn)情況下就是一次會話,關(guān)閉此web瀏覽器(注意是此web瀏覽器,不是此標(biāo)簽頁)即被清除,還可以通過拼接“expires=過期時間”字符串來手動設(shè)置過期時間,例如“var date = new Date (); ?date.setDate (date.getDate () + 1); ?document.cookie = “age=33;expires=”+ date.toGMTString () + “;”;”,當(dāng)沒有到達(dá)所設(shè)置的過期時間時,即使關(guān)閉了此web瀏覽器,再打開此web瀏覽器此cookie還是存在,當(dāng)?shù)竭_(dá)了所設(shè)置的過期時間時,即使沒有關(guān)閉此web瀏覽器,此cookie也會被立即清除,某一個html文件給此web瀏覽器所設(shè)置的cookie可以被在此二級域名文件夾下跟此html文件同級/其下級目錄的其它html文件所訪問,當(dāng)也想被在此二級域名文件夾下其上級目錄的其它html文件所訪問時,就需要在設(shè)置cookie的時候在結(jié)尾處添加一個path屬性,取值是此二級域名文件夾的根目錄,例如“document.cookie = “name=zs;path=/;”;”,由于在一個網(wǎng)站文件夾中包括若干個二級域名文件夾,例如“www.it666.com”和“edu.it666.com”就是在同一個網(wǎng)站文件夾中的兩個不同的二級域名文件夾,所以,當(dāng)想要讓某一個二級域名文件夾內(nèi)的html文件給此web瀏覽器所設(shè)置的cookie能夠被其它二級域名文件夾內(nèi)的html文件所訪問時,就需要在結(jié)尾處再添加一個domain屬性,取值是此網(wǎng)站文件夾的根目錄(即根域名),以后當(dāng)我們想要保存一個cookie時,使用這種形式即可,例如“document.cookie = “name=zs;path=/;domain=it666.com;”;”,document對象訪問它的domain屬性可以返回此html網(wǎng)頁的web服務(wù)器域名(主機(jī)名)字符串,當(dāng)想要封裝一個基于jQuery.js的插件時,則插件名稱的固定格式為“jQuery.插件的作用.js”,例如“jQuery.cookie.js”,插件里邊固定的寫法為“;() ();”,在兩個小括號中寫一個立即執(zhí)行的匿名函數(shù)(即閉包),并傳入jQuery和window,例如“;(function ($, window) {}) (jQuery, window);”,H5新增的存儲方案是sessionStorage和localStorage,跟cookie一樣,sessionStorage和localStorage也是此html網(wǎng)頁保存到此web瀏覽器中的數(shù)據(jù)(key-value格式的文本信息),但它倆僅僅是保存到了此web瀏覽器中,不參與跟web服務(wù)器的通信,而且它倆的大小均限制在5M左右,詳情可參考網(wǎng)址“dev-test.nemikor.com/web-storage/support-test/”,sessionStorage的生命周期是僅在此標(biāo)簽頁下有效,關(guān)閉此標(biāo)簽頁/web瀏覽器后就會被清除,而且不能設(shè)置過期時間,經(jīng)常用于存儲表單數(shù)據(jù),因為當(dāng)用戶注冊某個東西的時候,就會填表單,填表單時有可能填完了第一頁還有第二頁,數(shù)據(jù)就會比較大,所以就需要大容量,并且在沒有關(guān)閉此標(biāo)簽頁的情況下,當(dāng)返回上一頁時,上一頁的數(shù)據(jù)會仍然存在,當(dāng)關(guān)掉了此標(biāo)簽頁時,表單中的數(shù)據(jù)就清空了,localStorage除非被清除,否則會永久保存,經(jīng)常用于存儲購物車的一些數(shù)據(jù),因為當(dāng)用戶在web瀏覽器上向購物車?yán)锾砑恿撕芏嗌唐窌r,在沒有買單的情況下,當(dāng)關(guān)閉了此web瀏覽器時,下一次用戶再通過此web瀏覽器打開購物車頁面,他上一次向購物車中所添加的商品仍然會存在,容量大并且永久存儲,通過cookie屬性、sessionStorage對象、和localStorage對象三種方式,切記都不能將敏感數(shù)據(jù)直接存儲到web瀏覽器,否則別人就有可能通過此web瀏覽器的F12->Application,然后點擊cookie/sessionStorage/localStorage來修改我們的數(shù)據(jù),sessionStorage/localStorage對象調(diào)用它的setItem方法可以給此web瀏覽器新增/修改一條sessionStorage/localStorage,例如“sessionStorage.setItem (“name”, “l(fā)nj”);(//以JSON的形式)”,sessionStorage/localStorage對象調(diào)用它的getItem方法可以返回此web瀏覽器sessionStorage/localStorage中傳入key所對應(yīng)的value,例如“sessionStorage.getItem (“name”);”,sessionStorage/localStorage對象調(diào)用它的removeItem方法可以刪除此web瀏覽器sessionStorage/localStorage中傳入key所指代的鍵值對,例如“sessionStorage.removeItem (“name”);”,sessionStorage/localStorage對象調(diào)用它的clear方法可以清空此web瀏覽器sessionStorage/localStorage中保存的所有數(shù)據(jù),例如“sessionStorage.clear ();”,同源策略(Same origin policy)是一種約定,它是web瀏覽器最核心最基本的安全功能,超文本傳輸協(xié)議、一級域名、二級域名、和端口號都相同的URL就叫做同源的URL,否則就叫做跨域的URL,例如在URL“http://www.it666.com:80/index.html”中,“http://”就叫做超文本傳輸協(xié)議,“it666.com”就叫做一級域名,“www.”就叫做二級域名,“:80”就叫做端口號,“/index.html”就叫做資源路徑,為了提升html網(wǎng)頁的性能,html網(wǎng)頁和數(shù)據(jù)一般都是單獨(dú)存儲在不同的web服務(wù)器上,但web瀏覽器只允許AJAX請求同源URL的數(shù)據(jù),不允許請求跨域URL的數(shù)據(jù),跨域請求的解決方案是“JSONP(JSON with Padding,即填充式JSON)”、“document.domain+iframe”、“l(fā)ocation.hash+iframe”、“window.name+iframe”、“window.postMessage”、和“flash等第三方插件”,但只有“JSONP”是目前常用的,由于通過<script>的src屬性既可以引入本地的數(shù)據(jù),還可以引入網(wǎng)絡(luò)的數(shù)據(jù),沒有同源與否的限制,所以我們可以通過<script>的src屬性來請求跨域的數(shù)據(jù),讓html網(wǎng)頁從跨域的URL來獲取數(shù)據(jù)的過程就叫做JSONP,通過JSONP從web服務(wù)器所獲取到的一般都不會是一個“變量”字符串,而是一句帶有參數(shù)的“函數(shù)的調(diào)用”字符串,這樣一來,通過所獲取到的數(shù)據(jù)就可以調(diào)用我們在本地所定義的函數(shù),而傳入的參數(shù)就是我們所需要的數(shù)據(jù),但是問題是,我們在本地所定義的函數(shù)名稱卻有可能是變化的、不確定的,解決方案是在URL后面添加點參數(shù),來動態(tài)的告訴web服務(wù)器我們在本地所定義的函數(shù)名稱是什么,例如“<script src=“http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test”></script>”,然后后端代碼可以“$cb = $_GET[“cb”]; ?echo $cb.“(666);”;(//在php中用“.”來拼接字符串)”,由于默認(rèn)情況下多個<script>的執(zhí)行是同步的,即只有前面的<script>執(zhí)行完畢,后面的<script>才會執(zhí)行,所以為了安全起見,請求跨域數(shù)據(jù)的<script>必須寫到后面,但是當(dāng)我們使用JS來動態(tài)的createElement script元素時,就不存在這個問題了,因為使用JS所動態(tài)createElement的script元素默認(rèn)就是異步的,會在最后執(zhí)行,例如“l(fā)et oScript = document.createElement (“script”); ?oScript.src = “http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test”; ?document.body.appendChild (oScript); ?function test (data) {console.log (data);}”,存儲在硬盤(rom)中的一些永久性的數(shù)據(jù)就叫做靜態(tài)數(shù)據(jù),當(dāng)計算機(jī)關(guān)閉之后再開啟,靜態(tài)數(shù)據(jù)依舊還在,只要你不主動刪掉或者硬盤沒壞,靜態(tài)數(shù)據(jù)永遠(yuǎn)都在,在程序運(yùn)行過程中,動態(tài)產(chǎn)生存儲在內(nèi)存(ram)中的臨時性數(shù)據(jù)就叫做動態(tài)數(shù)據(jù),當(dāng)計算機(jī)關(guān)閉之后,這些臨時性數(shù)據(jù)就會被清除,之所以不把所有的應(yīng)用程序加載到硬盤中去執(zhí)行,主要原因就是內(nèi)存的訪問速度比硬盤快N倍,靜態(tài)數(shù)據(jù)是可以轉(zhuǎn)成動態(tài)數(shù)據(jù)的,例如硬盤上存儲的視頻加載到播放軟件上播放,動態(tài)數(shù)據(jù)也是可以轉(zhuǎn)成靜態(tài)數(shù)據(jù)的,例如拍照軟件拍的一張照片寫入到本地硬盤,將編譯型語言編寫好的代碼通過編譯工具編譯之后存儲在硬盤上的一個二進(jìn)制文件就叫做應(yīng)用程序,應(yīng)用程序在操作系統(tǒng)中的一次執(zhí)行過程就叫做進(jìn)程,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,同一個應(yīng)用程序在操作系統(tǒng)中每執(zhí)行一次都會開啟一個進(jìn)程,并且所開啟的多個進(jìn)程的空間是相互獨(dú)立的,互不影響的,所以應(yīng)用程序和進(jìn)程之間是一對多的關(guān)系,進(jìn)程中的一個執(zhí)行實例就叫做線程,線程是應(yīng)用程序執(zhí)行的最小單元,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位,在一個進(jìn)程中有一個默認(rèn)的線程,叫做主線程,主線程的作用是執(zhí)行應(yīng)用程序中的業(yè)務(wù)邏輯代碼,除此之外,開發(fā)人員在編寫應(yīng)用程序的時候還可以手動創(chuàng)建一些其它的線程,所以進(jìn)程和線程之間也是一對多的關(guān)系,例如啟動迅雷這個應(yīng)用程序,系統(tǒng)會創(chuàng)建一個迅雷進(jìn)程,并且此迅雷進(jìn)程會有一個默認(rèn)的主線程,用于執(zhí)行迅雷默認(rèn)的業(yè)務(wù)邏輯,當(dāng)我們利用迅雷同時執(zhí)行多個下載任務(wù)的時候,迅雷就會創(chuàng)建多個線程,將不同的下載任務(wù)放到不同的線程中執(zhí)行,當(dāng)一個進(jìn)程中只有一個線程并且有多個任務(wù)需要執(zhí)行時,只有前一個任務(wù)執(zhí)行完畢,后一個任務(wù)才能執(zhí)行,這就叫做串行,當(dāng)一個進(jìn)程中有多個線程并且有多個任務(wù)需要執(zhí)行時,就可以一個線程執(zhí)行一個任務(wù),多個線程都可以同時執(zhí)行任務(wù),這就叫做并行,JS是單線程的編程語言,之所以被設(shè)計成單線程的,是因為它作為web瀏覽器的腳本語言,主要的用途是與用戶的互動,以及操作DOM元素,假如JS被設(shè)計成多線程的,當(dāng)有一個線程要修改DOM元素中的內(nèi)容,而另一個線程卻要刪除該DOM元素時,web瀏覽器就會有很復(fù)雜的同步問題,不知道該以哪個線程為準(zhǔn),正是由于JS是單線程的編程語言,所以JS代碼都是串行的,當(dāng)前面的代碼沒有執(zhí)行完畢時,后面的代碼就不能執(zhí)行,并且JS代碼分為同步代碼和異步代碼,只有“滿足一定條件才可執(zhí)行的回調(diào)函數(shù)”(比如事件所綁定的回調(diào)函數(shù))是異步代碼,除此以外的都是同步代碼,在程序運(yùn)行時,會先從上至下依次執(zhí)行所有的同步代碼,當(dāng)遇到異步代碼時,會將異步代碼放到所有代碼最后的事件循環(huán)中,當(dāng)所有同步代碼都執(zhí)行完畢時,系統(tǒng)會不斷檢測事件循環(huán)中的異步代碼是否滿足條件,當(dāng)滿足條件時,就執(zhí)行相應(yīng)的回調(diào)函數(shù),但是當(dāng)在同一個回調(diào)函數(shù)中需要按照一定順序執(zhí)行很多回調(diào)函數(shù)時(即異步操作),勢必就會出現(xiàn)回調(diào)函數(shù)的層層嵌套,當(dāng)所嵌套的層數(shù)太多時,就會導(dǎo)致代碼的閱讀性和可維護(hù)性大大降低(即回調(diào)地獄),所以在ES6中就新增了一種異步編程的解決方案,即Promise類,new Promise所創(chuàng)建的實例對象就叫做Promise對象(ES6新增),創(chuàng)建Promise對象的格式為“new Promise (function (resolve, reject) {});”,所傳入的回調(diào)函數(shù)不是異步的,是會立即執(zhí)行的,形參resolve和reject接收到的是回調(diào)函數(shù),在不調(diào)用resolve/reject回調(diào)函數(shù)時,自身的[[PromiseStatus]]/[[PromiseState]]值默認(rèn)就是“pending”(代表默認(rèn)狀態(tài)),[[PromiseValue]]/[[PromiseResult]]值默認(rèn)就是undefined,在調(diào)用resolve回調(diào)函數(shù)時(等價于Promise.resolve (參數(shù));),當(dāng)不傳參/所傳入的實參不是一個額外的Promise對象時,自身的[[PromiseStatus]]值是“resolved”/“fulfilled”(代表成功狀態(tài)),自身的[[PromiseValue]]值是undefined/所傳入的實參,當(dāng)所傳入的實參是一個額外的Promise對象時,自身的狀態(tài)和[[PromiseValue]]值也會繼承于所傳入的實參,在調(diào)用reject回調(diào)函數(shù)時(等價于Promise.reject (參數(shù));),自身的[[PromiseStatus]]值是“rejected”(代表失敗狀態(tài)),自身的[[PromiseValue]]值是undefined/所傳入的實參,當(dāng)一個Promise對象的狀態(tài)一旦變?yōu)槌晒?失敗時,就是永久性的,不會再發(fā)生變化了,Promise對象調(diào)用它的then方法可以監(jiān)聽調(diào)用者的成功/失敗狀態(tài),在成功/失敗狀態(tài)下執(zhí)行參數(shù)1/2回調(diào)函數(shù),并且調(diào)用者的[[PromiseValue]]值也會傳入?yún)?shù)1/2回調(diào)函數(shù)中,在沒有傳入?yún)?shù)2回調(diào)函數(shù),并且參數(shù)1回調(diào)函數(shù)的返回值不是一個額外的Promise對象時,當(dāng)調(diào)用者是成功狀態(tài)時,then方法的返回值是一個繼承了調(diào)用者狀態(tài)并且[[PromiseValue]]值是參數(shù)1回調(diào)函數(shù)返回值的新Promise對象,當(dāng)調(diào)用者是失敗狀態(tài)時,then方法的返回值是一個繼承了調(diào)用者狀態(tài)和[[PromiseValue]]值的新Promise對象,在傳入了參數(shù)2回調(diào)函數(shù),并且所執(zhí)行的參數(shù)1/2回調(diào)函數(shù)的返回值不是一個額外的Promise對象時,then方法的返回值是一個成功狀態(tài)并且[[PromiseValue]]值是參數(shù)1/2回調(diào)函數(shù)返回值的新Promise對象,在無論有沒有傳入?yún)?shù)2回調(diào)函數(shù),只要所執(zhí)行的參數(shù)1/2回調(diào)函數(shù)的返回值是一個額外的Promise對象時,then方法的返回值是一個繼承了此額外Promise對象狀態(tài)和[[PromiseValue]]值的新Promise對象,當(dāng)調(diào)用then方法時,還可以捕獲上一個調(diào)用者在調(diào)用then/catch方法時所出現(xiàn)的錯誤,并將所捕獲到的錯誤傳入?yún)?shù)2回調(diào)函數(shù)中,并執(zhí)行此參數(shù)2回調(diào)函數(shù),Promise對象調(diào)用它的catch方法可以監(jiān)聽調(diào)用者的失敗狀態(tài),在失敗狀態(tài)下執(zhí)行所傳入的回調(diào)函數(shù),并且調(diào)用者的[[PromiseValue]]值也會傳入此回調(diào)函數(shù)中,當(dāng)傳入回調(diào)函數(shù)的返回值是一個額外的Promise對象時,catch方法的返回值是一個繼承了此額外Promise對象狀態(tài)和[[PromiseValue]]值的新Promise對象,當(dāng)傳入回調(diào)函數(shù)的返回值不是一個額外的Promise對象時,catch方法的返回值是一個成功狀態(tài)并且[[PromiseValue]]值是傳入回調(diào)函數(shù)的返回值的新Promise對象,catch方法其實是then方法的語法糖,相當(dāng)于“then (undefined, () => {})”,對于一個失敗狀態(tài)的Promise對象,必須予以監(jiān)聽,否則就會報錯,而成功狀態(tài)的Promise對象則無所謂,所以,當(dāng)我們想要分別調(diào)用then和catch方法來監(jiān)聽調(diào)用者成功/失敗的狀態(tài)時,建議使用鏈?zhǔn)骄幊毯喜⒊梢痪浯a來寫,一旦分成了兩句代碼來寫,當(dāng)調(diào)用者是失敗狀態(tài)時,then方法的返回值是一個繼承了調(diào)用者狀態(tài)的新Promise對象,這樣一來,此失敗狀態(tài)的新Promise對象就沒有得到監(jiān)聽,進(jìn)而就報錯了,當(dāng)調(diào)用catch方法時,還可以捕獲上一個調(diào)用者在調(diào)用then/catch方法時所發(fā)生的錯誤,并將所捕獲到的錯誤傳入回調(diào)函數(shù)中,并執(zhí)行此回調(diào)函數(shù),例如“l(fā)et p1 = new Promise (function (resolve, reject) {resolve ();} ); ?p1.then (function () {console.log (“成功”); ?xxx} ).catch (function (e) {console.log (“失敗”, e);} );(//控制臺會打印“失敗 ReferenceError: xxx is not defined”)”,綜上所述,可以根據(jù)Promise對象的成功/失敗狀態(tài)并調(diào)用then/catch方法來實現(xiàn)用同步流程表示異步操作,以此避免回調(diào)函數(shù)層層嵌套的問題,由于JS是單線程的,所編寫的代碼都是串行的,所以一旦前面的代碼出現(xiàn)錯誤,程序就會被中斷,后續(xù)的代碼就不會執(zhí)行了,當(dāng)是自身編寫代碼的問題時,就手動修復(fù)bug,當(dāng)是外界的一些可預(yù)見的錯誤時,就可以使用try catch來捕獲錯誤,既可以保證程序不被中斷,增強(qiáng)程序的容錯性和健壯性,還可以記錄錯誤原因,以便于后續(xù)優(yōu)化、迭代、更新,try catch是一個整體,不能分開,必須同時出現(xiàn),格式為“try {可能遇到錯誤的代碼;} catch (e) {捕獲錯誤的代碼塊;}”,當(dāng)try中的代碼沒有出現(xiàn)錯誤時,就會正常執(zhí)行,而catch中的代碼就不執(zhí)行了,當(dāng)try中的代碼出現(xiàn)了錯誤時,catch中的代碼就會執(zhí)行,并把錯誤的原因傳遞給catch中的形參e,Promise類對象調(diào)用它的all方法可以在傳入一個由Promise對象所組成的數(shù)組時,當(dāng)所有的元素都是成功狀態(tài)時,返回值是一個成功狀態(tài)并且[[PromiseValue]]值是所有元素的[[PromiseValue]]值所組成數(shù)組的新Promise對象,當(dāng)所有的元素不都是成功狀態(tài)時,返回值是一個失敗狀態(tài)并且[[PromiseValue]]值是首個失敗狀態(tài)元素的[[PromiseValue]]值的新Promise對象,all方法的應(yīng)用場景是當(dāng)進(jìn)行批量加載時,要么一起成功,要么一起失敗,其實調(diào)用all方法時也可以傳入一個普通數(shù)組(即非Promise對象所組成的數(shù)組),此時all方法的返回值是一個成功狀態(tài)并且[[PromiseValue]]值是所傳入數(shù)組的Promise對象,Promise類對象調(diào)用它的race方法可以在傳入一個由Promise對象所組成的數(shù)組時,返回值是一個繼承了狀態(tài)變化最快元素狀態(tài)和[[PromiseValue]]值的新Promise對象,race方法的應(yīng)用場景是接口調(diào)試,超時處理,全局對象調(diào)用它的fetch方法可以實現(xiàn)基于Promise的AJAX(ES6新增),可以傳入一個URL字符串和一個對象,例如“fetch (“http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34”, {method: “get”});”,“fetch (“http://127.0.0.1/jQuery/Ajax/41.php”, {method: “post”, body: JSON.stringify ({teacher: “l(fā)nj”, age: 34}) });”,返回值是一個成功狀態(tài)并且[[PromiseValue]]值是Response對象的Promise對象,Response對象調(diào)用它的text方法可以返回一個成功狀態(tài)并且[[PromiseValue]]值是web服務(wù)器所輸出數(shù)據(jù)的新Promise對象,Response對象調(diào)用它的json方法可以返回一個web服務(wù)器響應(yīng)狀態(tài)并且[[PromiseValue]]值是web服務(wù)器所輸出JSON被轉(zhuǎn)成的JS對象的新Promise對象,axios.js是一個基于Promise的HTTP類庫,即網(wǎng)絡(luò)請求插件,可以在web瀏覽器和NodeJS中使用,axios.js插件跟fetch方法的功能是一樣的,但axios.js插件更完善也更安全,建議使用axios.js插件就可以了,可以在GitHub上下載此插件,解壓之后,在里面的dist文件夾中,就會看到axios.js和axios.min.js文件,將它倆復(fù)制到我們自己的項目中就可以了,可以在“www.kancloud.cn/yunye/axios/234845”網(wǎng)址查看一下它的中文文檔,axios類對象調(diào)用它的get/post方法可以返回一個web服務(wù)器響應(yīng)狀態(tài)并且[[PromiseValue]]值是Response對象的Promise對象,例如“axios.get (“http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34”);(//可以改寫為“axios.get (“http://127.0.0.1/jQuery/Ajax/41.php”, {params: {teacher: “l(fā)nj”, age: 34} });”)”,“axios.post (“http://127.0.0.1/jQuery/Ajax/41.php”, {teacher: “l(fā)nj”, age: 34});”,Response對象訪問它的data屬性可以返回web服務(wù)器所輸出的數(shù)據(jù)即result對象(當(dāng)數(shù)據(jù)是JSON時會自動轉(zhuǎn)成JS對象),axios類對象調(diào)用它的all方法可以同時執(zhí)行多個“axios.get ();”/“axios.post ();”(即同時執(zhí)行多個并發(fā)請求),格式為“axios.all ([axios.get (‘/user/12345’), axios.get (‘/user/12345/permissions’)] ).then (axios.spread (function (result1, result2) {console.log (result1, result2);} ) );(//result1和result2接收到的分別是第一個和第二個get請求所獲取到的Response對象)”,在企業(yè)開發(fā)中,項目分為開發(fā)和部署兩個階段,在這兩個階段中,項目所存儲的位置是不同的,項目上線前存儲在企業(yè)內(nèi)部的測試服務(wù)器上,項目上線后存儲在企業(yè)的正式服務(wù)器上(例如上線前URL是“http://127.0.0.1/jQuery/Ajax/41.php”,上線后URL是“http://192.199.13.14/jQuery/Ajax/41.php”),當(dāng)每次向web服務(wù)器發(fā)送請求時,假如都將所請求的完整URL寫在請求中,那么當(dāng)項目上線時,就需要大量修改所請求的URL,所以為了解決這個問題,我們可以設(shè)置一個全局的URL根地址,等到項目上線時只需要修改根地址即可,例如“axios.defaults.timeout = 2000;(//設(shè)置請求的超時時間,當(dāng)兩秒鐘之內(nèi)服務(wù)器沒有返回數(shù)據(jù)時,就會報錯) ?axios.defaults.baseURL = “http://127.0.0.1”;(//設(shè)置全局的URL根地址) ?axios.post (“/jQuery/Ajax/41.php”, {teacher: “l(fā)nj”, age: 34}).then (function (res) {console.log (res.data);} ).catch (function (e) {console.log (e);} );”,Symbol()是ES6中新增的基本數(shù)據(jù)類型,由于Symbol不是函數(shù),所以前面不能加new,Symbol()就代表一個獨(dú)一無二的值,數(shù)據(jù)類型是symbol,由于Symbol()和Symbol()分別是兩個獨(dú)一無二的值,所以Symbol()和Symbol()不全等,symbol類型的數(shù)據(jù)可以轉(zhuǎn)成字符串和布爾類型的數(shù)據(jù),但不能轉(zhuǎn)成數(shù)值類型的數(shù)據(jù),symbol類型的數(shù)據(jù)也不能做任何運(yùn)算,當(dāng)給第三方的插件/框架動態(tài)的添加了重名的屬性/方法時,勢必就會將此插件/框架中原有的屬性/方法覆蓋掉,所以為了避免這種情況的發(fā)生,插件/框架的作者/使用者就可以使用Symbol()來動態(tài)的添加屬性/方法,也可以同時在Symbol()的小括號中添加一個字符串來設(shè)置一個標(biāo)記,這個標(biāo)記僅僅是為了便于區(qū)分,沒有任何其它含義,當(dāng)想要在一個對象的內(nèi)部手動添加symbol類型的屬性/方法時,必須首先在此對象的外部將Symbol()保存到一個變量中,然后在此對象的內(nèi)部再給此變量加一個中括號來充當(dāng)屬性/方法的名稱,并且當(dāng)想要訪問/調(diào)用它們時,不能使用“.”的方式,只能使用中括號包裹相應(yīng)變量的方式,例如“l(fā)et name = Symbol(“name”); ?let say = Symbol(“say”); ?let obj = {[name]: “l(fā)nj”, [say]: function () {console.log (“say”);} }; ?console.log (obj[name]);(//“l(fā)nj”) ?obj[Symbol(“name”)] = “it666”;(//不會將原有的覆蓋掉)”,使用for in循環(huán)是無法遍歷一個對象symbol類型的屬性/方法的,Object類對象調(diào)用它的getOwnPropertySymbols方法可以返回傳入對象中symbol類型屬性/方法名稱所組成的數(shù)組,標(biāo)準(zhǔn)和規(guī)范就叫做接口,這里的接口和現(xiàn)實中的接口是一樣的,例如USB接口就有它的標(biāo)準(zhǔn)和規(guī)范,所以A廠商生產(chǎn)的USB線可以插到B廠商電腦的USB接口上,Iterator叫做迭代器,即迭代程序,也是一種接口(即標(biāo)準(zhǔn)和規(guī)范),Iterator接口規(guī)定了不同數(shù)據(jù)類型的統(tǒng)一訪問機(jī)制,此統(tǒng)一訪問機(jī)制主要是指能被for of循環(huán)所遍歷,默認(rèn)情況下,Array、Map、Set、String、和TypedArray類的實例對象,以及函數(shù)的arguments對象和NodeList對象(DOM節(jié)點的集合)都實現(xiàn)了Iterator接口,也就是都能被for of循環(huán)所遍歷,當(dāng)一個數(shù)據(jù)(對象)能被for of循環(huán)所遍歷時,此數(shù)據(jù)(對象)就一定有一個叫做[Symbol.iterator]的方法,此數(shù)據(jù)(對象)調(diào)用它的[Symbol.iterator]方法可以返回一個可迭代對象,例如“l(fā)et arr = [1, 3, 5]; ?let it = arr[Symbol.iterator] ();(//變量it的值是一個可迭代對象)”,此可迭代對象調(diào)用它的next方法可以每次調(diào)用都返回一個擁有兩個屬性的對象,例如“{value: 1, done: false}”,value值是當(dāng)前所遍歷到的元素,done值是true/false,true代表遍歷完畢,false代表還沒有遍歷完畢,所以,for of循環(huán)的內(nèi)部實現(xiàn)原理就是不斷地調(diào)用next方法,并把value值賦值給變量value,并判斷是否遍歷完畢,當(dāng)遍歷完畢時,就不再調(diào)用next方法了,只有實現(xiàn)了Iterator接口的數(shù)據(jù)(對象),才能夠?qū)ζ溥M(jìn)行解構(gòu)賦值和使用擴(kuò)展運(yùn)算符,Generator函數(shù)是ES6提供的一種異步編程解決方案,只需要在普通函數(shù)的function函數(shù)聲明符后面加上*即可,在Generator函數(shù)作用域內(nèi)可以使用yield操作符(只能在Generator函數(shù)中使用)封裝多個狀態(tài),并且可以將代碼塊劃分成多個部分,因此Generator函數(shù)又可以理解為是一個狀態(tài)機(jī),例如“function* gen () {console.log (“123”); ?yield “aaa”; ?console.log (“567”); ?yield 1 + 1;}”,調(diào)用Generator函數(shù)后,此函數(shù)中所封裝的代碼不會立即執(zhí)行,無論此函數(shù)有沒有返回值,都會返回一個可迭代對象,此可迭代對象調(diào)用它的next方法可以每次調(diào)用都會執(zhí)行此Generator函數(shù)作用域內(nèi)yield操作符所劃分的一部分代碼,返回值是一個擁有兩個屬性的對象,value值是yield操作符所作用的值,done值是true/false(true代表已經(jīng)結(jié)束了,不能再迭代了,false代表還未結(jié)束,還可以再迭代),在調(diào)用next方法的時候可以傳入一個實參,此實參會作為上一個yield操作符的返回值,Generator函數(shù)的應(yīng)用場景是可以讓函數(shù)返回多個值,例如“function* calculate (a, b) {yield a + b; ?yield a - b;} ?let it = calculate (10, 5); ?console.log (it.next ().value); ?console.log (it.next ().value);”,可以在任意對象上快速部署Iterator接口,例如“l(fā)et obj = {name: “l(fā)nj”, age: 34, gender: “man”}; ?function* gen () {let keys = Object.keys (obj); ?for (let i = 0; i < keys.length; i++) {yield obj[keys[i] ];} } ?obj[Symbol.iterator] = gen; ?let it = obj[Symbol.iterator] (); ?console.log (it.next () );”,可以實現(xiàn)用同步流程來表示異步操作,例如“function request () {return new Promise (function (resolve, reject) {setTimeout (function () {resolve (“獲取到的數(shù)據(jù)”);}, 1000);} );} ?function* gen () {yield request (); ?yield request (); ?yield request ();} ?let it = gen (); ?it.next ().value.then (function (data) {console.log (data, 1); ?return it.next ().value;}).then (function (data) {console.log (data, 2); ?return it.next ().value;}).then (function (data) {console.log (data, 3);} );”,async函數(shù)聲明符是ES8中新增的一個聲明符,用于定義一個異步函數(shù)(即解決異步問題的函數(shù),可以使代碼按順序同步執(zhí)行),跟普通函數(shù)的用法一樣,當(dāng)調(diào)用async函數(shù)時,其作用域中的代碼會自動從上至下的執(zhí)行,使用await操作符(只能在async函數(shù)中使用)可以暫停當(dāng)前async函數(shù)的執(zhí)行,當(dāng)其所作用的Promise對象(即操作數(shù))變?yōu)槌晒顟B(tài)時,它的[[PromiseValue]]值會作為此await操作符的返回值,然后繼續(xù)執(zhí)行此async函數(shù),當(dāng)其所作用的Promise對象(即操作數(shù))變?yōu)槭顟B(tài)時,此web瀏覽器的控制臺會throw一個錯誤和它的[[PromiseValue]]值,就不再繼續(xù)執(zhí)行此async函數(shù)了,當(dāng)其所作用的操作數(shù)不是一個Promise對象,而僅僅是一個常量時(比如123),系統(tǒng)會把這個常量包裝成Promise.resolve (xx),同理,當(dāng)其沒有操作數(shù)時,系統(tǒng)會把它的操作數(shù)包裝成Promise.resolve (undefined),一個async函數(shù)無論最后return啥,當(dāng)調(diào)用它的時候,返回的都是一個繼承了此await操作符的操作數(shù)狀態(tài)的Promise對象(不存在await操作符就返回成功狀態(tài)的Promise對象),其[[PromiseValue]]值是此async函數(shù)return的值,在一個調(diào)用了async函數(shù)的函數(shù)作用域中,當(dāng)想要讓代碼按順序同步執(zhí)行時,必須將此函數(shù)也變成async函數(shù),并且在調(diào)用了async函數(shù)的位置await一下才好使(即雙async await),例如“async function gen () {let res1 = await request (); ?console.log (res1, 1); ?let res2 = await request (); ?console.log (res2, 2); ?let res3 = await request (); ?console.log (res3, 3);} ?gen ();(//上面的Generator函數(shù)用同步流程來表示異步操作是這種寫法的內(nèi)部實現(xiàn)原理,這種寫法可以看作是它的縮寫)”
九、zepto.js類庫
zepto.js是一個輕量級的針對現(xiàn)代高級瀏覽器的JS類庫,是專門用于移動端的輕量級的jQuery.js,它與jQuery.js有著類似的api,當(dāng)你會使用jQuery.js時,你就會使用zepto.js,由于jQuery.js更多的是用在PC端,所以jQuery.js考慮了很多低級瀏覽器的兼容性問題,代碼更多,體積更大,并且做動畫的內(nèi)部實現(xiàn)原理是利用JS操作DOM元素,由于zepto.js更多的是用在移動端,所以zepto.js則是直接拋棄了低級瀏覽器的適配問題,代碼更少,體積更小,并且做動畫的內(nèi)部實現(xiàn)原理是利用CSS3中相關(guān)的屬性,zepto.js英文官方文檔的網(wǎng)址是“zeptojs.com”,中文官方文檔的網(wǎng)址是“www.css88.com/doc/zeptojs_api”,zepto.js采用了模塊化的開發(fā),將不同的功能放到了不同的模塊(js文件)中,在使用的過程中可以按需引入,也就是需要什么功能就引入什么模塊,從官方網(wǎng)站下載的zepto.js已經(jīng)包含了一些默認(rèn)的模塊,從GitHub下載的zepto.js需要我們自己手動引入每一個模塊,后續(xù)學(xué)習(xí)了NodeJS后,我們也可以自己定制,將不同的模塊打包成一個模塊,由于移動端的事件很多,例如單擊、雙擊、輕掃、捏合、和拖拽等等,所以當(dāng)我們在移動端使用click來監(jiān)聽點擊事件時,系統(tǒng)需要花費(fèi)100~300毫秒判斷到底是什么事件,而移動端對事件響應(yīng)速度的要求很高,事件響應(yīng)越快用戶體驗就越好,所以當(dāng)我們需要在移動端監(jiān)聽點擊事件時,請使用tap事件,tap事件是zepto.js自己封裝的一個事件,解決了原生click事件100~300毫秒的延遲問題,例如“$ (“div”).tap (function () {console.log (“被點擊了”);} );”,給zepto的DOM元素集合所綁定的swipe/swipeLeft/swipeRight/swipeUp/swipeDown事件的觸發(fā)條件是手指在此集合所包含的DOM元素上輕掃/向左/向右/向上/向下輕掃