创建新元素(或选择现有元素)时,jQuery 会在集合中返回元素。许多刚接触 jQuery 的开发者会认为这个集合是一个数组。毕竟,它有一个从零开始的 DOM 元素序列、一些熟悉的数组函数和一个 .length
属性。实际上,jQuery 对象比这复杂得多。
链接 DOM 和 DOM 元素
文档对象模型(简称 DOM)是 HTML 文档的表示形式。它可能包含任意数量的 DOM 元素。从高层次上讲,DOM 元素可以被认为是网页的“一部分”。它可能包含文本和/或其他 DOM 元素。DOM 元素由类型描述,例如 <div>
、<a>
或 <p>
,以及任意数量的属性,例如 src
、href
、class
等。如需更全面的描述,请参阅 W3C 的官方 DOM 规范。
元素具有与任何 JavaScript 对象一样的属性。这些属性包括 .tagName
等属性和 .appendChild()
等方法。这些属性是通过 JavaScript 与网页交互的唯一途径。
链接 jQuery 对象
事实证明,直接使用 DOM 元素可能会很尴尬。jQuery 对象定义了 许多 方法,以改善开发人员的体验。jQuery 对象的一些好处包括
兼容性 – DOM 方法的实现因浏览器供应商和版本而异。以下代码段尝试设置存储在 target
中的 <tr>
元素的内部 HTML
1
2
3
|
|
在许多情况下,这都能正常工作,但在大多数版本的 Internet Explorer 中会失败。在这种情况下,推荐的方法是改用纯 DOM 方法。通过将 target
元素包装在 jQuery 对象中,这些边缘情况得到了解决,并且在所有受支持的浏览器中都实现了预期结果
1
2
3
4
5
|
|
便利性 – 还有很多常见的 DOM 操作用例,使用纯 DOM 方法难以实现。例如,在 target
元素之后插入存储在 newElement
中的元素需要一个相当冗长的 DOM 方法
1
2
3
4
5
6
7
|
|
通过将 target
元素包装在 jQuery 对象中,同样的任务变得简单得多
1
2
3
4
5
6
7
|
|
在大多数情况下,这些细节只是阻碍您实现目标的“陷阱”。
链接 将元素放入 jQuery 对象
当使用 CSS 选择器调用 jQuery 函数时,它将返回一个 jQuery 对象,该对象包装与该选择器匹配的任何元素。例如,编写
1
2
3
|
|
headings
现在是一个 jQuery 对象,其中包含页面上已有的所有 <h1>
标签。可以通过检查 headings
的 .length
属性来验证这一点
1
2
3
4
5
|
|
如果页面有多个 <h1>
标签,则此数字将大于 1。如果页面没有 <h1>
标签,则 .length
属性将为零。检查 .length
属性是确保选择器成功匹配一个或多个元素的常用方法。
如果目标是仅选择第一个标题元素,则需要执行另一步骤。有许多方法可以实现此目的,但最直接的方法是 .eq()
函数。
1
2
3
4
5
|
|
现在 firstHeading
是一个 jQuery 对象,其中仅包含页面上的第一个 <h1>
元素。并且由于 firstHeading
是一个 jQuery 对象,因此它具有 .html()
和 .after()
等有用的方法。jQuery 还有一个名为 .get()
的方法,它提供了一个相关函数。它不返回 jQuery 封装的 DOM 元素,而是返回 DOM 元素本身。
1
2
3
|
|
或者,由于 jQuery 对象是“类似数组的”,因此它支持通过方括号进行数组下标
1
2
3
|
|
在任一情况下,firstHeadingElem
都包含原生 DOM 元素。这意味着它具有 .innerHTML
等 DOM 属性和 .appendChild()
等方法,但没有 .html()
或 .after()
等 jQuery 方法。firstHeadingElem
元素更难操作,但在某些情况下需要使用它。其中一个情况就是进行比较。
链接 并非所有 jQuery 对象都创建 ===
关于这种“包装”行为的一个重要细节是,每个包装对象都是唯一的。即使使用相同的选择器创建对象或包含对完全相同的 DOM 元素的引用,这一点也是正确的。
1
2
3
4
|
|
虽然 logo1
和 logo2
是以相同的方式创建的(并且包装相同的 DOM 元素),但它们不是同一个对象。例如
1
2
3
|
|
但是,这两个对象包含相同的 DOM 元素。.get()
方法可用于测试两个 jQuery 对象是否具有相同的 DOM 元素。
1
2
3
4
5
6
7
8
9
|
|
许多开发人员会在包含 jQuery 对象的变量名称前加上 $
,以便于区分。这种做法并没有什么神奇之处——它只是帮助一些人跟踪不同变量包含的内容。前面的示例可以重写为遵循此约定
1
2
3
4
5
6
7
8
9
|
|
此代码的功能与上面的示例相同,但更易于阅读。
无论使用哪种命名约定,区分 jQuery 对象和原生 DOM 元素都非常重要。原生 DOM 方法和属性不存在于 jQuery 对象上,反之亦然。诸如“event.target.closest 不是函数”和“TypeError: Object [object Object] 没有 setAttribute 方法”之类的错误消息表明存在这种常见错误。
链接 jQuery 对象不是“实时”的
给定一个包含页面上所有段落元素的 jQuery 对象
1
2
3
|
|
…人们可能会期望随着文档中添加和删除 <p>
元素,内容会随着时间的推移而增长和收缩。jQuery 对象不会以这种方式表现。包含在 jQuery 对象中的元素集合不会更改,除非明确修改。这意味着该集合不是“实时”的——它不会随着文档的更改而自动更新。如果文档在创建 jQuery 对象后可能已更改,则应通过创建一个新对象来更新该集合。这就像重新运行相同的选择器一样简单
1
2
3
|
|
链接 总结
尽管 DOM 元素提供了创建交互式网页所需的所有功能,但使用起来可能很麻烦。jQuery 对象封装了这些元素,以简化此体验并使常见任务变得容易。使用 jQuery 创建或选择元素时,结果将始终封装在一个新的 jQuery 对象中。如果情况需要原生 DOM 元素,则可以通过 .get()
方法和/或数组式下标访问它们。