失去jQuery膨胀
核心要点
-
NodeList.js 作为 jQuery 的 DOM 操作替代方案,提供类似的功能,但体积更小(压缩后 4k),并利用了原生浏览器 API 的改进。
-
与 jQuery 不同,NodeList.js 将节点数组视为单个节点,从而实现更简洁的代码和更轻松的 NodeList 对象操作。
-
NodeList.js 包含用于设置和获取属性、调用特定于元素的方法以及访问 NodeList 中节点的特殊方法,以及等同于 jQuery 的
prevObject
属性的owner
属性。 -
NodeList.js 与特定版本以后的主流浏览器兼容(Firefox 6 、Safari 5.0.5 、Chrome 6 、IE 9 、Opera 11.6 ),并自动更新以包含浏览器新增的方法/属性。
p.tip { background-color: rgba(128,128,128,0.05); border-top-right-radius: 5px; border-bottom-right-radius: 5px; padding: 15px 20px; border-left: 10px solid rgba(128,128,128,0.075); }
近年来,jQuery 已成为 Web 上事实上的 JavaScript 库。它消除了许多跨浏览器的不一致性,并为客户端脚本添加了一层受欢迎的语法糖。它抽象化处理的主要痛点之一是 DOM 操作,但自 jQuery 问世以来,原生浏览器 API 已得到显著改进,“你可能不需要 jQuery” 的理念开始流行起来。
原因如下:
- jQuery 包含许多您不需要或不使用的功能(因此其体积不必要地庞大)。
- jQuery 对太多人来说承担了太多功能。通常,较小的库可以更好地完成某些任务。
- 就 DOM 操作而言,浏览器 API 现在可以完成 jQuery 大部分的功能。
- 浏览器 API 现在更加同步,例如使用
addEventListener
代替attachEvent
。
问题何在?
问题在于,与 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 }); // 错误:nodes.forEach 不是函数
因此,您必须执行以下操作:
var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }
或者甚至只能使用“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);
// 返回我的 NodeList
此方法在后台使用 querySelectorAll(selector)
。
但它与 jQuery 相比如何?
很高兴您提出这个问题。让我们将原生 JS、jQuery 和 NodeList.js 进行比较。
假设我们有三个按钮:
让我们将每个按钮的文本更改为“点击我”:
原生 JS:
var buttons = document.querySelectorAll('button'); // 返回浏览器无用的 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
属性设置为“点击我”。然后,NodeList.js 将对 NodeList 中的每个节点执行此操作。很巧妙,对吧?
如果我们想要方法链(类似于 jQuery),我们会执行以下操作,这将返回对 NodeList 的引用:
$$('button').set('textContent', 'Click Me');
现在,让我们向每个按钮添加一个点击事件监听器:
原生 JS:
var buttons = document.querySelectorAll('button'); // 返回浏览器无用的 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'); // 或将 jQuery 与原生混合使用 `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'); });
不错!这演示了我们添加自己方法的方式:
var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数
NodeList.js 对数组方法的支持
NodeList.js 确实继承自 Array.prototype
,但不是直接继承,因为某些方法已更改,因此使用它们与 NodeList(节点数组)一起使用是有意义的。
push
和 unshift
例如:push
和 unshift
方法只能将节点作为参数,否则会抛出错误:
var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }
因此,push
和 unshift
都返回 NodeList 以允许方法链,这意味着它与 JavaScript 的原生 Array#push
或 Array#unshift
方法不同,后者接受任何内容并返回数组的新长度。如果我们确实想要 NodeList 的长度,我们只需使用 length
属性。
这两个方法,就像 JavaScript 的原生数组方法一样,都会更改 NodeList。
concat
concat
方法将接受以下内容作为参数:
[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });
concat
是一个递归方法,因此这些数组可以像我们希望的那样深,并且会被展平。但是,如果传递的数组中的任何元素不是节点、NodeList 或 HTMLCollection,它将抛出错误。
concat
返回一个新的 NodeList,就像 javascript 的 Array#concat
方法一样。
pop
、shift
、map
、slice
、filter
pop
和 shift
方法都可以采用可选参数,说明要从 NodeList 中弹出或移位多少个节点。与 JavaScript 的原生 Array#pop
或 Array#shift
不同,后者总是弹出或移位数组中的一个元素,而不管传递什么作为参数。
如果每个映射值都是一个节点,map
方法将返回一个 NodeList;如果不是,则返回映射值的数组。
slice
和 filter
方法的作用与在真实数组中的作用一样,但会返回一个 NodeList。
由于 NodeList.js 没有直接继承自 Array.prototype
,因此如果在加载 NodeList.js 后向 Array.prototype
添加方法,则不会继承该方法。
您可以在此处查看 NodeList.js 的其余数组方法。
特殊方法
NodeList.js 有四个独特的方法,以及一个名为 owner
的属性,它等同于 jQuery 的 prevObject
属性。
get
和 set
方法:
某些元素具有特定于该类型元素的属性(例如,锚标记上的 href
属性)。这就是为什么 $$('a').href
将返回未定义的原因——因为它不是 NodeList 中每个元素都继承的属性。这就是我们如何使用 get
方法访问这些属性的方法:
var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数
set
方法可用于为每个元素设置这些属性:
var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }
set
还返回 NodeList 以允许方法链。我们可以在 textContent
等方面使用它(两者都等效):
[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });
我们还可以在一次调用中设置多个属性:
var nodes = document.querySelectorAll('div'); nodes.item(0) === nodes[0]; // true
以上所有操作都可以使用任意属性完成,例如 style
:
var buttons = document.querySelectorAll('button'); // 返回浏览器无用的 NodeList for(var i = 0, l = buttons.length; i < l; i++) { buttons[i].textContent = 'Click Me'; }
call
方法
call
方法允许您调用特定于元素的方法(例如,视频元素上的 pause
):
$('button').text('Click Me');
item
方法
item
方法等同于 jQuery 的 eq
方法。它返回一个 NodeList,其中只包含传递索引的节点:
$$('button').textContent = 'Click Me';
owner
属性
owner
属性等同于 jQuery 的 prevObject
。
$$('button').set('textContent', 'Click Me');
btns.style
返回样式数组,而 owner
将返回 style
所映射的 NodeList。
NodeList.js 兼容性
我的库与所有主要的新浏览器兼容,如下所述。
浏览器 版本
结论
现在我们终于可以使用有用的 NodeList 对象了!
对于大约 4k 的压缩大小,您可以获得上述所有功能以及更多功能,您可以在 NodeList.js 的 GitHub 存储库中了解所有这些功能。
由于 NodeList.js 使用浏览器作为依赖项,因此无需进行任何升级。每当浏览器向 DOM 元素添加新方法/属性时,您都可以通过 NodeList.js 自动使用这些方法/属性。所有这一切都意味着您唯一需要担心的弃用是浏览器删除的方法。这些通常是使用率非常低的方法,因为我们不能破坏 Web。
那么您怎么看?您会考虑使用这个库吗?是否缺少任何重要功能?我很乐意在下面的评论中听到您的意见。
关于使用 NodeList.js 进行 DOM 操作的常见问题
NodeList 和 HTMLCollection 有什么区别?
NodeList 和 HTMLCollection 都是节点集合。它们之间的主要区别在于 NodeList 可以包含任何节点类型,而 HTMLCollection 是元素节点的集合。HTMLCollection 也是动态的,这意味着当文档结构发生更改时,它会自动更新。另一方面,NodeList 是静态的,不会更新以反映文档中的更改。
如何将 NodeList 转换为数组?
您可以使用 Array.from()
方法或展开运算符将 NodeList 转换为数组。以下是如何操作:
var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数
为什么 jQuery 选择器返回 prevObject 而不是普通元素?
jQuery 的链式机制通过在进行更改之前存储之前的对象来工作。这允许您使用 .end()
方法恢复到之前的状态。如果您想获取实际的 DOM 元素,可以使用 .get()
方法或数组表示法。
如何循环遍历 NodeList?
您可以使用 for 循环、for...of 循环或 forEach()
方法循环遍历 NodeList。这是一个使用 for 循环的示例:
var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }
jQuery 中 .prev() 方法有什么用?
jQuery 中的 .prev()
方法用于选择所选元素的紧邻前一个同级元素。如果提供了选择器,则只有在匹配该选择器时才会检索前一个同级元素。
jQuery 在 2022 年仍然相关吗?
虽然 jQuery 在发布时是一个改变游戏规则的东西,但现代 JavaScript 生态系统已经发生了显着变化。许多使 jQuery 受欢迎的功能现在都内置于 JavaScript 本身。但是,jQuery 仍然被广泛使用和维护,它可能是某些项目的良好选择。
如何从 NodeList 中选择特定节点?
您可以使用数组表示法或 item()
方法从 NodeList 中选择特定节点。以下是如何操作:
[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });
我可以在 NodeList 上使用 map、filter 和 reduce 方法吗?
NodeList 不是数组,因此它没有像 map、filter 和 reduce 这样的方法。但是,您可以将 NodeList 转换为数组,然后使用这些方法。
querySelector 和 querySelectorAll 有什么区别?
querySelector
返回文档中与指定的 CSS 选择器匹配的第一个元素,而 querySelectorAll
返回与 CSS 选择器匹配的所有元素的 NodeList。
如何检查 NodeList 是否为空?
您可以通过检查其 length
属性来检查 NodeList 是否为空。如果长度为 0,则 NodeList 为空。以下是如何操作:
var nodes = document.querySelectorAll('div'); nodes.item(0) === nodes[0]; // true
以上是失去jQuery膨胀的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。
