js nodelist
近年来,jQuery已成为网络上事实上JavaScript库。 它消除了许多跨浏览器的不一致之处,并在客户端脚本中添加了可喜的语法糖。 它抽象化的主要痛点之一是DOM操作,但是自其诞生以来,本机浏览器API有了显着改善,并且您可能不需要jQuery的想法开始流行。
原因如下:
- jQuery包含了许多您不需要或不使用的功能(因此权重是不必要的)。
- jQuery对太多人来说太多了。 通常,较小的库可以更好地完成某些任务。
- 在DOM操作方面,浏览器API现在可以完成jQuery的大部分工作。
- 浏览器的API现在更加同步,例如使用
addEventListener
而不是attatchEvent
。
所以有什么问题?
问题在于,与jQuery相比,使用原始(或普通)JavaScript进行DOM操作可能会很痛苦。 这是因为您必须读写更多的冗余代码,并处理浏览器的无用NodeList 。
首先让我们看一下根据MDN的NodeList
:
NodeList对象是节点的集合,例如由Node.childNodes和document.querySelectorAll方法返回的那些节点。
有时还有实时的NodeList (可能会引起混淆):
在某些情况下,NodeList是一个实时集合,这意味着DOM中的更改会反映在集合中。 例如,Node.childNodes处于活动状态。
这可能是一个问题,因为您无法分辨哪些是实时的,哪些是静态的。 除非您从NodeList
删除每个节点,然后检查NodeList
是否为空。 如果为空,那么您将拥有一个活动的NodeList
(这是一个坏主意)。
而且浏览器也没有提供任何有用的方法来操纵这些NodeList
对象。
例如,不幸的是,不可能使用forEach
遍历节点:
var nodes = document.querySelectorAll('div');
nodes.forEach(function(node) {
// do something
});
// Error: nodes.forEach is not a function
因此,您必须执行以下操作:
var nodes = document.querySelectorAll('div');
for(var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
// do something
}
甚至还可以使用“ hack”:
[].forEach.call(document.querySelectorAll('div'), function(node) {
// do something
});
浏览器的本机NodeList
只有一种方法: item 。 这将通过索引从NodeList
返回一个节点。 当我们可以像访问数组一样(使用array[index]
)访问该节点时,它是完全没有用的:
var nodes = document.querySelectorAll('div');
nodes.item(0) === nodes[0]; // true
这就是NodeList.js的用处 -使得使用浏览器的本机API操纵DOM就像使用jQuery一样容易,但是仅需4k即可。
解决方案
我创建NodeList.js的原因是我一直使用本机DOM API,但希望使其更加简洁,以便在编写代码时消除大量冗余(例如for
循环)。
NodeList.js是本机DOM API的包装,它使您可以像对待单个节点一样操作节点数组(又称为NodeList
)。 这为您提供了比浏览器的本机NodeList
对象更多的功能。
如果这对您来说听起来不错,请从官方的GitHub存储库中获取NodeList.js的副本,然后继续本教程的其余部分。
用法:
选择DOM节点很简单:
$$(selector); // returns my NodeList
此方法在querySelectorAll(selector)
使用querySelectorAll(selector)
。
但是它如何与jQuery叠在一起?

免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
很高兴你问。 让我们将香草JS,jQuery和NodeList.js放在首位。
假设我们有三个按钮:
<button></button>
<button></button>
<button></button>
让我们将每个按钮的文本更改为“ Click Me” :
香草JS:
var buttons = document.querySelectorAll('button'); // returns browser's useless NodeList
for(var i = 0, l = buttons.length; i < l; i++) {
buttons[i].textContent = 'Click Me';
}
jQuery的:
$('button').text('Click Me');
NodeList.js:
$$('button').textContent = 'Click Me';
在这里,我们看到NodeList.js可以有效地将NodeList
视为单个节点。 也就是说,我们已经引用了NodeList
,我们只是将其textContent
属性设置为“ Click Me” 。 然后NodeList.js将在每个节点上执行此NodeList
。 整洁吧?
如果我们想要方法链接(jQuery类),我们将执行以下操作,返回对NodeList
的引用:
$$('button').set('textContent', 'Click Me');
现在,我们向每个按钮添加一个click
事件监听器:
香草JS:
var buttons = document.querySelectorAll('button'); // returns browser's useless NodeList
for(var i = 0, l = buttons.length; i < l; i++) {
buttons[i].addEventListener('click', function() {
this.classList.add('clicked');
});
}
jQuery的:
$('button').on('click', function() {
$(this).addClass('click');
// or mix jQuery with native using `classList`:
this.classList.add('clicked');
});
NodeList.js:
$$('button').addEventListener('click', function() {
this.classList.add('clicked');
});
好的,因此jQuery on
方法相当不错。 我的库使用浏览器的本机DOM API(因此为addEventListener
),但并不能阻止我们为该方法创建别名:
$$.NL.on = $$.NL.addEventListener;
$$('button').on('click', function() {
this.classList.add('clicked');
});
真好! 这恰好演示了我们添加自己的方法的方式:
$$.NL.myNewMethod = function() {
// loop through each node with a for loop or use forEach:
this.forEach(function(element, index, nodeList) {...}
// where `this` is the NodeList being manipulated
}
数组方法上的NodeList.js
NodeList.js确实从Array.prototype继承,但不是直接继承,因为某些方法已更改,因此可以将它们与NodeList
(节点数组)一起使用。
推入和放开
例如: push和unshift方法只能将节点作为参数,否则它们将引发错误:
var nodes = $$('body');
nodes.push(document.documentElement);
nodes.push(1); // Uncaught Error: Passed arguments must be a Node
因此push
和unshift
返回NodeList
以允许方法链接,这意味着它与JavaScript的本机Array#push
或Array#unshift
方法不同,后者可以接受任何内容并返回Array
的新长度。 如果我们确实想要NodeList
的长度,我们只使用length
属性。
就像JavaScript的本机Array
方法一样,这两种方法都会更改NodeList
。
康卡特
concat方法将以下内容作为参数:
-
Node
-
NodeList
(浏览器的本机版本和NodeList.js版本) -
HTMLCollection
-
Array of Nodes
-
Array of NodeList
-
Array of HTMLCollection
concat
是一种递归方法 ,因此这些数组可以像我们想要的那样深,并且将被展平。 但是,如果传递的数组中的任何元素都不属于Node
, NodeList
或HTMLCollection
则它将引发Error
。
concat
确实会返回一个新的NodeList
,就像javascript的Array#concat
方法一样。
弹出,移位,地图,切片,过滤器
pop和shift方法都可以使用一个可选参数来确定要从NodeList
pop
或shift
多少个节点。 与JavaScript的本机Array#pop
或Array#shift
,无论将什么作为参数传递,后者总是会pop
或shift
数组中的一个元素。
如果每个映射值都是一个Node
,则map方法将返回一个NodeList
如果不是,则返回一个映射值的数组。
slice和filter方法的行为就像在实际数组上一样,但是将返回NodeList
。
由于NodeList.js并不直接从继承Array.prototype
如果一个方法被添加到Array.prototype
NodeList.js被加载之后,也不会被继承。
您可以在此处检查其余的NodeList.js数组方法 。
特殊方法
NodeList.js独有四种方法,还有一个名为owner
的属性,它等同于jQuery的prevObject
属性。
get
和set
方法:
有些元素具有该类元素独有的属性(例如,anchor标签上的href
属性)。 这就是$$('a').href
返回undefined
原因-因为它是NodeList
中并非每个元素都继承的属性。 这就是我们使用get方法访问这些属性的方式:
$$('a').get('href'); // returns array of href values
set方法可用于为每个元素设置这些属性:
$$('a').set('href', 'https://sitepoint.com/');
set
还返回NodeList
以允许方法链接。 我们可以在textContent
东西上使用它(两者都是等效的):
$$('button').textContent = 'Click Me';
$$('button').set('textContent', 'Click Me'); // returns NodeList so you can method chain
我们还可以在一个调用中设置多个属性:
$$('button').set({
textContent: 'Click Me',
onclick: function() {...}
});
以上所有操作都可以通过任意属性来完成,例如style
:
$$('button').style; // this returns an `Array` of `CSSStyleDeclaration`
$$('button').style.set('color', 'white');
$$('button').style.set({
color: 'white',
background: 'lightblue'
});
call
方式
通过call方法 ,您可以调用元素独有的那些方法(例如,在视频元素上pause
):
$$('video').call('pause'); // returns NodeList back to allow Method Chaining
item
方法
item方法等效于jQuery的eq方法 。 它返回一个NodeList
,它仅包含传递的索引的节点:
$$('button').item(1); // returns NodeList containing the single Node at index 1
owner
财产
owner属性与jQuery的prevObject
等效。
var btns = $$('button');
btns.style.owner === btns; // true
btns.style
返回一个样式数组, owner
返回给您映射style
的NodeList
。
NodeList.js兼容性
我的媒体库与所有主要的新浏览器兼容,如下所述。
浏览器 | 版 |
---|---|
火狐 | 6+ |
苹果浏览器 | 5.0.5+ |
Chrome | 6+ |
IE浏览器 | 9+ |
歌剧 | 11.6+ |
结论
现在,我们终于可以使用一个有用的NodeList
对象了!
只需花大约4k的时间,您就可以得到上面提到的所有功能,并且可以在NodeList.js的GitHub存储库中学习更多的功能。
由于NodeList.js使用浏览器作为依赖项,因此无需进行任何升级。 每当浏览器向DOM元素添加新的方法/属性时,您都可以通过NodeList.js自动使用这些方法/属性。 所有这一切都意味着您唯一需要担心的弃用方法是浏览器摆脱的方法。 这些通常使用率很低,因为我们无法破坏网络。
所以你怎么看? 这是您要考虑使用的库吗? 是否缺少任何重要功能? 我希望在下面的评论中收到您的来信。
翻译自: https://www.sitepoint.com/dom-manipulation-with-nodelist-js/
js nodelist