首先我們來(lái)看下封裝函數(shù)的兩種方式
function getSiblings(node){} //直接通過(guò)function關(guān)鍵字封裝函數(shù)
var dom = {} //創(chuàng)建一個(gè)命名空間把函數(shù)放入命名空間
dom.getSiblings(node)
dom.addClass(node, {a: true, b: false})
上面兩種方法封裝的函數(shù)的node如果想放到前面
node.getSiblings()
node.addClass()
如上代碼所示這樣調(diào)用的話該如何做呢
- 方法一:擴(kuò)展 Node 接口(即公有屬性/原型)
直接在 Node.prototype 上加函數(shù) - 方法二:新的接口 如下代碼所示
window.jQuery = function(nodeOrSelector){
let nodes={}
if(typeof nodeOrSelectoe==='string'){
let temp=document.querySelectorAll(nodeOrSelector)
for(let i=0;i<temp.length;i++){
nodes[i]=temp[i]
}
nodes.length=temp.length
}else{
nodes={
0: nodeOrSelector,
length: 1
}
}
nodes.addClass=function(classes){
classes.forEach((value)=>{
for(let i=0;i<nodes.length;i++){
nodes[i].classList.add(value)
}
})
}
nodes.setText=function(text){
for(let i=0;i<nodes.length;i++){
nodes[i].textContent=text
}
}
return nodes
}
window.$ = jQuery
var $div = $('div')
$div.addClass('red')
$div.setText('hi')
接下來(lái)通過(guò)上面代碼講解下jQuery是如何實(shí)現(xiàn)的
- 首先在window這個(gè)對(duì)象下創(chuàng)建一個(gè)屬性jQuery,它的值是一個(gè)函數(shù)蛾扇,函數(shù)的參數(shù)是一個(gè)變量被碗,函數(shù)的返回值是一個(gè)對(duì)象苛谷。
- 我們先初始化一個(gè)對(duì)象用來(lái)存放我們的函數(shù)郊酒。
- 通過(guò)一個(gè)if判斷這個(gè)變量的值是否為字符串,如果是字符串我們就用DOM的API querySelectorAll方法去尋找匹配的元素節(jié)點(diǎn)并且用一個(gè)變量存儲(chǔ)起來(lái),由于返回的是一個(gè)Node集合對(duì)象档冬,他的原型指向了Node.prototype瞧柔,我們并不需要這個(gè)原型上的方法,所以我們把這個(gè)集合遍歷一遍取出存放到我們初始化的對(duì)象上宋彼,并且把length屬性也賦值過(guò)去弄砍,這樣我們的對(duì)象的原型就直接指向了Object.prototype。這樣就會(huì)干凈很多输涕,我們的原型鏈上沒(méi)有那些我們不需要的東西音婶。
- 如果值不是字符串,那么傳進(jìn)來(lái)的就是一個(gè)元素節(jié)點(diǎn)對(duì)象莱坎,我們只需要把它放到我們的初始化對(duì)象下標(biāo)為0的地方衣式,并且length屬性的值為1。
- 然后我們自定義的函數(shù)放在這個(gè)對(duì)象里面檐什,這樣做的好處是即使外面有同名函數(shù)也不會(huì)產(chǎn)生覆蓋碴卧,這種做法叫做無(wú)侵入。
- 在最后記得把這個(gè)對(duì)象作為返回值傳出去乃正。
這樣我們就可以通過(guò)var $div = $('div')去把我們要找的元素節(jié)點(diǎn)封裝成對(duì)象的屬性然后再返回這個(gè)對(duì)象住册。
$div.addClass('red') 我們就可以這樣去調(diào)用對(duì)象里面的方法了。
jQuery就是這樣把一些難用難記DOM API封裝成新的好用的API的瓮具。當(dāng)然jQuery并不是這么簡(jiǎn)單荧飞,只是講解下如何像jQuery那樣去封裝函數(shù)凡人。