摘要:優(yōu)化代碼的原則就是提出重復(fù)的代碼。新的叫它,它返回一個對象,對象里面有兩個函數(shù),也就是和,并用初始化。當(dāng)然了這只是的基本原理,實(shí)際遠(yuǎn)比它復(fù)雜。
學(xué)習(xí)了DOM api 之后,做些簡單的小練習(xí)
在HTML寫5個無序列表
獲取item3的所以的兄弟節(jié)點(diǎn)如何做呢?
DOM 提供了nextSbiling`previousSbiling,有人說用parentNode.children獲取,但是這樣做item3`也在里面了,所以就自己做一個API,
我把這個名字叫做getSiblings
//node 是參數(shù),傳遞item3進(jìn)來,傳出item3的所有兄弟節(jié)點(diǎn)。 function getSiblings(node){ var allChildren = node.parentNode.children //先獲取item3所有兄弟節(jié)點(diǎn),保存在allChildren中,是一個偽數(shù)組 //剔除item3節(jié)點(diǎn) var array = {length:0}; //創(chuàng)建一個偽數(shù)組,存儲item3節(jié)點(diǎn)的所有兄弟節(jié)點(diǎn),因?yàn)槭莻螖?shù)組,所以給它添加length:0 for(var i=0; i如果要給item3添加或刪除class,用自帶的API 只能一個個添加,看下面
item3.classList.add("a") item3.classList.add("b") item3.classList.add("c") item3.classList.remove("b")如果自己做一個API,是不是可以實(shí)現(xiàn)批量添加呢
//node classes 是參數(shù),要添加或刪除class的節(jié)點(diǎn),這里傳遞的classes是偽數(shù)組 function addOrRemoveClass(node,classes){ for(var aaa in classes){ //用for循環(huán)遍歷classes的key var a = classes[aaa]; //用一個變量來存儲classes的value if(a){ //用if循環(huán)判斷classes的value是true還是false node.classList.add(aaa); //如果是true,則添加key }else { node.classList.remove(aaa);//否則移除 } } } addOrRemoveClass(item3,{"a":true,"b":false,"c":true});上面代碼if...else...中有重復(fù)代碼,可優(yōu)化成下面這樣。
優(yōu)化代碼的原則就是提出重復(fù)的代碼。
var methondName = a?"add":"remove"; //add、remove要用字符串 node.classList[methondName](aaa)下面先看添加class怎么實(shí)現(xiàn)。
foreach接受一個函數(shù)參數(shù),函數(shù)參數(shù)是數(shù)組的value和key,可以看之前總結(jié)的Array基本概念//node classes 是參數(shù),要添加或刪除class的節(jié)點(diǎn),這里classes是數(shù)組 function addClass(node,classes){ classes.forEach(value => node.classList.add(value)) //把數(shù)組的`value`添加到class中 } addClass(item3,[a,b,c])用這樣的方法創(chuàng)建好用的API,但有個不足的地方,這些都是全局變量,如果在大項(xiàng)目中,很容易覆蓋別人的變量。
所以把自己寫的API 添加到Node的原型上
Node.prototype.getSiblings = function(){ var allChildren = this.parentNode.children; //this指代調(diào)用時前面的那個 var array = {length:0}; for(var i=0; ithis.classList.add(value)) } item3.getSibllings.call(item3) //用call的話,直接指定this,不用call的話,是隱示指向`.`前面那個 item3.addClass.call(item3,["a","b","c"]) 不理解this的可以看函數(shù)小知識點(diǎn)
在原型上面添加方法也和上面一樣有弊端,第一項(xiàng)目一大,所有人都在原型上面添加,就會造成原型里面很混亂;第二你也不知道別人有沒寫和你一樣的方法,這又會造成覆蓋的問題。
因?yàn)檫@是在Node上直接寫的,那我能不能自己寫一個Node這樣就不會和人家重名了,就算遇到,改一個名字唄。新的Node叫它Node2,它返回一個對象,對象里面有兩個函數(shù),也就是getSiblings和addClass,并用node2初始化。
//Node2相當(dāng)于原來的Node window.Node2 = funcuntion(){ return{ //返回2個方法 getSiblings:function(){}, addClass:function(){} } } var node2 = Node2(""item3) //初始化 node2.getSiblings.call() //正常調(diào)用 node2.addClass.call()getSiblings和addClass方法還是和前面一樣,之前我們用this來指代node,但是這里用this的話會指向node2,而我們要操作的是node,所以要把this變成node才行。
window.Node2 = function(node){ //參數(shù)是要操作的節(jié)點(diǎn) return{ getSiblings:function(){ var allChildren = node.parentNode.children; //這里不能用this 了,因?yàn)橛胻his會變成前面的.node2,而這里我們要操作的是node var array = {length:0}; for(var i = 0; i < allChildren.length;i++){ if(allChildren[i] !== node){ array[array.length] = allChildren[i]; array.length++; } } return array; }, addClass:function(classes){ classes.forEach(value => node.classList.add(value)) } } } var node2 = Node2(item3); node2.getSiblings(); //這里為什么不需要傳入節(jié)點(diǎn),因?yàn)樵诔跏蓟臅r候,已經(jīng)把節(jié)點(diǎn)傳進(jìn)去了 node2.addClass(["a","b","c"]);如果把Node2改成jQuery其他都不變,是不是也可以,看下面,getSiblings和addClass里面的方法就不寫了。
window.jQuery = funcuntion(){ return{ getSiblings:function(){}, addClass:function(){} } } var node2 = jQuery(item3) node2.getSiblings.call() node2.addClass.call()jQuery就是一個升級的DOM,它接受一個參數(shù),然后返回一個新的對象,這個新對象有新的API,就是這邊的getSiblings和addClass,它們的內(nèi)部是怎么實(shí)現(xiàn)的呢,還是去調(diào)用瀏覽器提供的API,區(qū)別是你就寫下面調(diào)用的API,一句話就可以了,而jQuery是在里面調(diào)用老的API,進(jìn)行復(fù)雜的轉(zhuǎn)換。
簡單的說jQuery就是接收一個參數(shù),返回給你一個新對象,你調(diào)用它提供的API 就可以了。
當(dāng)然了這只是jQuery的基本原理,實(shí)際遠(yuǎn)比它復(fù)雜。
再來看下面的例子,如果我傳遞的是選擇器怎么操作呢?
window.jQuery = function(nodeOrSelector){ var node; //存儲if判斷后的參數(shù) if(typeof nodeOrSelector === "string"){ //因?yàn)檫x擇器是以字符串的形式傳遞進(jìn)來的,所以先要用if進(jìn)行判斷,typeof用來判斷類型的 node = document.querySelector(nodeOrSelector); //如果是字符串,就是選擇器,根據(jù)選擇器找到對應(yīng)的節(jié)點(diǎn),并保存在聲明的變量中 }else{ node = nodeOrSelector; //如果不是,直接保存在變量中 } return{ getSiblings:function(){ var allChildren = node.parentNode.children; var array={length:0}; for(var i = 0 ;i < allChildren.length;i++){ if(allChildren[i] !== node){ array[array.length] = allChildren[i]; array.length++; } } return array; }, addClass:function(classes){ classes.forEach(value => node.classList.add(value)) } } } var node2 = jQuery("#item3"); //傳遞選擇器,使用字符串的形式表示 node2.getSiblings(); node2.addClass(["red"]);初始化的時候傳遞了一個選擇器,jQuery 內(nèi)部先進(jìn)行判斷,傳進(jìn)來的是不是字符串,如果是,我就找到對應(yīng)的節(jié)點(diǎn);后面的操作和之前講的一樣。
我們再來升級下jQuery,如果我想同時操作5個節(jié)點(diǎn)呢?看下面:
window.jQuery = function(nodeOrSelector){ var nodes = {}; //querySelectorAll輸出的是偽數(shù)組,所以用來存儲的變量也要初始化成偽數(shù)組 if(typeof nodeOrSelector === "string"){ //用typeof判斷傳進(jìn)來的類型 var temp = document.querySelectorAll(nodeOrSelector);//如果傳進(jìn)來的是選擇器,就獲取對應(yīng)所有的節(jié)點(diǎn),querySelectorAll輸出的是偽數(shù)組 //因?yàn)楂@取到的不是純凈的偽數(shù)組(原型不是直接指向Object),先用臨時變量存儲,再用for循環(huán)遍歷一遍就可以了 for(var i = 0; i < temp.length; i++){ nodes[i] = temp[i] } nodes.length = temp.length; //把臨時變量的length長度賦值給nodes,下面遍歷時需要用到 }else if(nodeOrSelector instanceof node){ //instanceof用來判斷傳進(jìn)來的是不是節(jié)點(diǎn),因?yàn)楣?jié)點(diǎn)只能傳進(jìn)來一個 nodes = { //因?yàn)樯厦嬗玫氖莻螖?shù)組,所以這邊也要一致,雖然節(jié)點(diǎn)是一個,但也要做成偽數(shù)組的形式 0:nodeOrSelector, length:1 }; } //這時偽數(shù)組內(nèi)部是{0,1,2,3,4}的屬性,沒有addclass的方法,所以這邊可以直接往里面添加方法 nodes.addClass = function(classes){ for(var i = 0; i < nodes.length; i++){ classes.forEach(value => nodes[i].classList.add(value)); //nodes不是元素,這邊操作是在元素身上,所以要for循環(huán)遍歷,動態(tài)添加 } } nodes.text = function(text){ if(text === undefined){ //這里默認(rèn)沒傳參數(shù)就是獲取節(jié)點(diǎn)文本 var texts = []; //文本最終是數(shù)組的形式 for(var i = 0; i < nodes.length; i++){ //遍歷nodes,就可以獲取到了 texts.push(nodes[i].textContent); } return texts; }else{ //有參數(shù)就是設(shè)置文本 for(var i = 0; i < nodes.length; i++){ nodes[i].textContent = text; } } } return nodes; //因?yàn)檎麄€jQuery內(nèi)部是一個偽數(shù)組,所以這邊返回出去了肯定也是一個偽數(shù)組了 } var node2 = jQuery("ul > li"); node2.addClass(["red"]); console.log(node2.text()); node2.text("hi");最后簡化一下jQuery ,初始化時的變量名最好帶上$,后面好辨認(rèn)。
window.$ = jQuery; var $node2 = $("item3");
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95103.html
摘要:就像一個大的功能庫,給我們返回一個有很多方法屬性的對象,然后我們調(diào)用它的方法屬性就行了。和一樣,使用鏈?zhǔn)酱a。一旦找到新的元素,之后的鏈就操作在新元素上,而不是一開始的元素。一般的變量無法使用方法,使用封裝,使其可以使用方法。 jQuery jQuery就像一個大的功能庫,給我們返回一個有很多方法、屬性的對象,然后我們調(diào)用它的方法、屬性就行了。 和Javascript一樣,使用鏈?zhǔn)酱a...
摘要:它能夠使得在不刷新瀏覽器的情況下,更改本地的前端代碼組件,瀏覽器自動更新預(yù)覽。直接集成了這項(xiàng)技術(shù),而且建立了專門的通道進(jìn)行錯誤的實(shí)時反饋。命令行提供了三個主要的命令,。服務(wù)器關(guān)于服務(wù)器,其實(shí)是內(nèi)部起了一個基于的服務(wù)器,外加進(jìn)行消息的通訊。 跟著初探了下flintjs,的確會很棒,超級熱更新! 學(xué)習(xí)地址: http://frontenddev.org/link/ali-11-11-...
摘要:后來在爬取不到讓我一度懷疑人生的時候巧合下,發(fā)現(xiàn)磁力鏈接有小寫字母,有長度的,有長度的。。 原文博客: 羞羞的node爬蟲 前言 學(xué)了一陣子node,除了用 express 寫東西,就沒怎么做過東西突然就想寫個 爬蟲 來玩一玩,而且還是爬一些羞羞的東西 使用模塊 SuperAgent 是個 http 方面的庫,可以發(fā)起 get 或 post 請求。 cheerio 大家可以理解成一個 ...
摘要:后來在爬取不到讓我一度懷疑人生的時候巧合下,發(fā)現(xiàn)磁力鏈接有小寫字母,有長度的,有長度的。。 原文博客: 羞羞的node爬蟲 前言 學(xué)了一陣子node,除了用 express 寫東西,就沒怎么做過東西突然就想寫個 爬蟲 來玩一玩,而且還是爬一些羞羞的東西 使用模塊 SuperAgent 是個 http 方面的庫,可以發(fā)起 get 或 post 請求。 cheerio 大家可以理解成一個 ...
閱讀 2080·2021-11-24 10:34
閱讀 3055·2021-11-22 11:58
閱讀 3712·2021-09-28 09:35
閱讀 1724·2019-08-30 15:53
閱讀 2771·2019-08-30 14:11
閱讀 1551·2019-08-29 17:31
閱讀 542·2019-08-26 13:53
閱讀 2142·2019-08-26 13:45