在 jQuery 中,要为特定元素添加 class 很方便,只需要使用调用addClass
方法即可,例如为所有 div 添加 一个叫 red 的 class 只需要写 $("div").addClass("red")
。这与使用浏览器 api 实现同样的功能相比要简洁明了不少。本文通过逐渐改进的方式,实现一个从调用角度上与其类似的 api。
首先,先使用最直接的方式实现功能,传入一组节点和一个类名,为这组节点添加这个类
addClass = function (nodes, className) {
nodes.forEach(function (el) {
el.classList.add(className)
})
}
let nodes = document.querySelectorAll('div')
addClass.call(undefined, nodes, 'red')
这个方式有个缺点是只能一次添加一个类,如果需要添加多个则需要调用多次,不太方便。因为我们可以借助函数中的arguments
获取到传入的所有(非this
)参数,所以 className 这个参数也可以舍去,下面是可以一次性添加多个类的实现。
addClass = function (nodes) {
let args = arguments
nodes.forEach(function (el) {
for (let i = 1; i < args.length; i++) {
el.classList.add(args[i])
}
})
}
let nodes = document.querySelectorAll('div')
addClass.call(undefined, nodes, 'red', 'foo')
对比 jQuery 中的实现可以发现,这里每次都要先获取到节点然后再操作,而使用 jQuery 则一般直接传入选择器。所以这里可以进一步改造,使其适应选择器和节点参数。
addClass = function (nodeOrSelector) {
let args = arguments
if (typeof nodeOrSelector === 'string') {
nodes = document.querySelectorAll(nodeOrSelector)
} else {
nodes = nodeOrSelector
}
nodes.forEach(function (el) {
for (let i = 1; i < args.length; i++) {
el.classList.add(args[i])
}
})
}
addClass.call(undefined, 'div', 'red', 'foo')
到这里,实际上与 jQuery 的 api 已经有几分相似之处了,但是这里有一个明显的问题,那就是如果用户自己也定义了一个 addClass,那么我们的 addClass 就会被覆盖掉。因此,我们应该创建一个“独立的区域”用来存放这个函数。
window.$ = {
addClass: function (nodeOrSelector) {
let args = arguments
if (typeof nodeOrSelector === 'string') {
nodes = document.querySelectorAll(nodeOrSelector)
} else {
nodes = nodeOrSelector
}
nodes.forEach(function (el) {
for (let i = 1; i < args.length; i++) {
el.classList.add(args[i])
}
})
}
}
$.addClass.call(undefined, 'div', 'red', 'foo')
改完以后和 jQuery 更像了,就差最后几步了。实际上,如果我们执行typeof $
(在引入了 jQuery的前提下),可以发现它实际上是个函数。也就是说其实应该模仿它,将上面的代码也封装成一个函数。完成后的完整代码如下:
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.red {color: red; background-color: black;}
</style>
</head>
<body>
<div>DIV1</div>
<div>DIV2</div>
<div>DIV3</div>
<script src="./main.js"></script>
</body>
</html>
// main.js
window.jQuery = function (nodeOrSelector) {
let nodes
if (typeof nodeOrSelector === 'string') {
nodes = document.querySelectorAll(nodeOrSelector)
} else {
nodes = {
0: nodeOrSelector,
length: 1,
}
}
nodes.addClass = function () {
let classArray = arguments
nodes.forEach(function (el) {
for (let className of classArray ){
el.classList.add(className)
}
})
}
return nodes
}
window.$ = window.jQuery
setTimeout(function () {
let $div = $('div')
$div.addClass('red', 'foo', 'bar')
}, 1000)
网友评论