实现一个jQuery的API

需求

在不使用jQuery函数库的情况下自制一个与jQuery类似的API
首先,确认以下两个需求:

1
2
3
var $div = $('div')
$div.addClass('red') // 可将所有 div 的 class 添加一个 red
$div.setText('hi') // 可将所有 div 的 textContent 变为 hi

创建

先创建一个新的window对象jQuery,它是一个函数,并返回带有参数新的对象

1
2
3
4
5
window.jQuery=function(node){
return{
addClass:function(node){},
setText:function(node){}
}

参数

1
var $div = $('div')

要实现这个功能,需要区分传入的参数是一个选择器还是节点,并以伪数组的形式返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
window.jQuery = function (nodeOrSelector) {
let nodes = {}
if (typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSelector)
for (let i = 0; i < temp.length; i++) {
nodes[i] = temp[i]
}
nodes.length = temp.length

} else if (nodeOrSelector instanceof Node) {
nodes = {
0: nodeOrSelector,
length: 1
}
}
}

如果只是单单实现所需要的功能,可以简化成

1
2
3
window.jQuery = function (nodeOrSelector) {
let nodes = document.querySelectorAll(nodeOrSelector)
}

需求实现

1
$div.addClass('red')// 可将所有 div 的 class 添加一个 red

nodes是一个伪数组。如果每个div都要添加class的话,需要一个for循环,然后每一次用DOM的方法里的classList.add功能对div添加class。

1
2
3
4
5
addClass: function (className) {
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList.add(className)
}
}

同理可实现

1
2
3
4
5
6
7
$div.setText('hi') // 可将所有 div 的 textContent 变为 hi

setText: function (text) {
for (let i = 0; i < nodes.length; i++) {
nodes[i].textContent=text
}
}

把addClass和setText的内容结合到函数内,得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
window.jQuery = function (nodeOrSelector) {
let nodes = {}
if (typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSelector)
for (let i = 0; i < temp.length; i++) {
nodes[i] = temp[i]
nodes.length = temp.length
}

} else if (nodeOrSelector instanceof Node) {
nodes = {
0: nodeOrSelector,
length: 1
}

}
return {
addClass: function (className) {
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList.add(className)
}
},
setText: function (text) {
for (let i = 0; i < nodes.length; i++) {
nodes[i].textContent=text
}
}
}
}
window.$ = jQuery