封裝兩個(gè)函數(shù)钟沛,一個(gè)用來(lái)獲取某個(gè)節(jié)點(diǎn)的兄弟姐妹,一個(gè)用來(lái)給元素添加類
現(xiàn)在有一個(gè)無(wú)序列表。循序漸進(jìn)棉钧,體會(huì)jQuery設(shè)計(jì)思想。
<!-- ul>li[id=item$]{選項(xiàng)$}*5 -->
<ul>
<li id="item1">選項(xiàng)1</li>
<li id="item2">選項(xiàng)2</li>
<li id="item3">選項(xiàng)3</li>
<li id="item4">選項(xiàng)4</li>
<li id="item5">選項(xiàng)5</li>
</ul>
封裝兩個(gè)函數(shù)
封裝一個(gè)獲取兄弟姐妹函數(shù)getSiblings
function getSiblings(node){ /* API */
var allChildren = node.parentNode.children ;
// 偽數(shù)組
var array = {
length: 0
}
// 獲取node的兄弟姐妹
for (let i = 0; i < allChildren.length; i++){
if(allChildren[i] !== node){
// array是偽數(shù)組涕蚤,沒(méi)有push方法
array[array.length] = allChildren[i];
array.length += 1;
}
}
return array
}
封裝添加類函數(shù)addClass
//添加的類用數(shù)組表示
function addClass(node,classes){
classes.forEach(value => {
node.classList.add(value)
});
}
命名空間
兩個(gè)函數(shù)不能就這么隨意的放著宪卿,賦予一個(gè)命名空間
// getSiblings,addClass作為yyydom對(duì)象的方法
window.yyydom = {}
yyydom.getSiblings = getSiblings
yyydom.addClass = addClass
yyydom.addClass(item2,['a','b'])
//這種調(diào)用方式并不好的诵,我們希望將node節(jié)點(diǎn)放在前面
把node放在前面進(jìn)行調(diào)用
有兩種方法:
- 擴(kuò)展 Node 接口,直接在 Node.prototype 上加函數(shù)
- 自己創(chuàng)建新的接口
1.篡改Node.prototype佑钾,添加函數(shù)
Node.prototype.getSiblings = function(){
var allChildren = this.parentNode.children ;
// 偽數(shù)組
var array = {
length: 0
}
// 獲取node的兄弟姐妹
for (let i = 0; i < allChildren.length; i++){
if(allChildren[i] !== this){
// array是偽數(shù)組西疤,沒(méi)有push方法
array[array.length] = allChildren[i];
array.length += 1;
}
}
return array
}
Node.prototype.addClass2 = function(classes){
classes.forEach(value => {
this.classList.add(value)
});
}
// 用call顯示this,call的第一個(gè)參數(shù)就是this
// item3.getSiblings()
// item3.getSiblings.call(item3) ,等價(jià)上
// item3.addClass(['q','w','e'])
// item3.addClass(item3,['q','w','e']) 等價(jià)上
但是休溶,在Node原型上增加方法也不好代赁,如果有多個(gè)人修改容易造成沖突。既然這樣兽掰,不如自己創(chuàng)建一個(gè)新Node構(gòu)造函數(shù)芭碍。自己動(dòng)手,豐衣足食孽尽。
2.自己創(chuàng)建新的接口(無(wú)侵入)
window.Node2 = function(node){
return {
getSiblings:function(){
var allChildren = node.parentNode.children ;
// 偽數(shù)組
var array = {
length: 0
}
// 獲取node的兄弟姐妹
for (let i = 0; i < allChildren.length; i++){
if(allChildren[i] !== node){
// array是偽數(shù)組豁跑,沒(méi)有push方法
array[array.length] = allChildren[i];
array.length += 1;
}
}
return array
},
addClass:function(classes){
classes.forEach(value => {
node.classList.add(value)
});
}
}
}
var node2 = Node2(item3)
node2.getSiblings()
node2.addClass(['p','o'])
構(gòu)造函數(shù)Node2返回一個(gè)新對(duì)象,這個(gè)對(duì)象有g(shù)etSiblings和addClass兩個(gè)方法泻云,里面還是調(diào)用的原生API艇拍。似乎離目標(biāo)越來(lái)越近了。
Node2是隨意取的宠纯,改為jQuery卸夕,于是
var node2 = jQuery(item3)
node2.getSiblings()
再進(jìn)一步,window.$ = jQuery婆瓜,再省略window快集,于是就變成了
var node2 = $(item3)
node2.getSiblings()
是不是很熟悉呢?
選擇器多樣化
目前我們所創(chuàng)建的構(gòu)造函數(shù)只能獲取節(jié)點(diǎn)廉白,如果是其他選擇器呢个初,比如$('ul>li:nth-child(3)'),那么需要加一些判斷
window.jQuery = function(nodeOrSelector){
//是否為字符串
if(typeof nodeOrSelector === 'string'){
//利用了原生的document.querySelector
node = document.querySelector(nodeOrSelector)
}else{
node = nodeOrSelector
}
return {
getSiblings:function(){
var allChildren = node.parentNode.children ;
// 偽數(shù)組
var array = {
length: 0
}
// 獲取node的兄弟姐妹
for (let i = 0; i < allChildren.length; i++){
if(allChildren[i] !== node){
// array是偽數(shù)組,沒(méi)有push方法
array[array.length] = allChildren[i];
array.length += 1;
}
}
return array
},
addClass:function(classes){
classes.forEach(value => {
node.classList.add(value)
});
}
}
}
//獲取列表第五個(gè)元素
var node2 = jQuery('ul>li:nth-child(5)')
// 給我舊的對(duì)象猴蹂,返回新的對(duì)象
node2.addClass(['red'])
那么要獲取多個(gè)節(jié)點(diǎn)呢院溺,這是里面就要用到document.querySelectorAll,而且部分邏輯也有變化
window.jQuery2 = function(nodeOrSelector){
let nodes //最后要返回的對(duì)象
if(typeof nodeOrSelector === 'string'){
nodes = document.querySelectorAll(nodeOrSelector) //偽數(shù)組
}else if(nodeOrSelector instanceof Node){
// 保證返回結(jié)果一致磅轻,都為偽數(shù)組
nodes = {
0: nodeOrSelector,
length: 1
}
}
//添加類
nodes.addClass = function(classes){
classes.forEach((value) => {
// 給nodes數(shù)組里每一項(xiàng)添加類
for (let i = 0;i < nodes.length; i++){
nodes[i].classList.add(value)
}
})
}
// 獲取元素文本
nodes.getText = function(){
var texts = []
for(let i = 0;i < nodes.length;i++){
texts.push(nodes[i].textContent)
}
return texts
}
// 設(shè)置文本
nodes.setText = function(text){
for(let i=0;i<nodes.length;i++){
nodes[i].textContent = text
}
}
// 兩者合并珍逸,這種在jQuery中非常常見(jiàn)
nodes.text = function(text){
if(text === undefined){
var texts = []
for(let i = 0;i < nodes.length;i++){
texts.push(nodes[i].textContent)
}
return texts
}else{
for(let i=0;i<nodes.length;i++){
nodes[i].textContent = text
}
}
}
return nodes
}
var node3 = jQuery2('ul>li')
node3.addClass(['red'])
node3.text('yyy')
//這大概就是最終體了