当创建新元素(或选择现有元素)时,jQuery返回集合中的元素。jQuery的许多开发人员都认为这个集合是一个数组。.length毕竟,它有一个零索引序列的DOM元素,一些熟悉的数组函数和一个属性。实际上,jQuery对象比这更复杂。
文档对象模型(简称DOM)是HTML文档的表示形式。它可能包含任意数量的DOM元素。在高层次上,DOM元素可以被认为是网页的“一块”。它可能包含文本和/或其他DOM元素。DOM元件由类型描述,如<div>,<a>,或<p>,和任何数量的属性如src,href,class等。有关更全面的描述,请参阅W3C官方的DOM规范。
元素具有任何JavaScript对象的属性。这些属性中的属性.tagName和方法类似.appendChild()。这些属性是通过JavaScript与网页进行交互的唯一方法。
事实证明,直接使用DOM元素可能会很尴尬。jQuery对象定义了许多方法来平滑开发人员的体验。jQuery对象的一些好处包括:
兼容性 - 元素方法的实现因浏览器供应商和版本而异。以下代码段尝试设置<tr>存储在以下内容中的元素的内部HTML target:
var target = document.getElementById( "target" );
target.innerHTML = "<td>Hello <b>World</b>!</td>";这在许多情况下起作用,但在大多数版本的Internet Explorer中都会失败。在这种情况下,推荐的方法是使用纯DOM方法。通过将target元素包装在一个jQuery对象中,这些边缘情况得到了照顾,预期的结果是在所有支持的浏览器中实现的:
// Setting the inner HTML with jQuery.
var target = document.getElementById( "target" );
$( target ).html( "<td>Hello <b>World</b>!</td>" );方便 - 还有很多常见的DOM操作用例,使用纯DOM方法难以实现。例如,插入元素之后存储newElement的target元素需要一个相当冗长的DOM方法:
// Inserting a new element after another with the native DOM API.
var target = document.getElementById( "target" );
var newElement = document.createElement( "div" );
target.parentNode.insertBefore( newElement, target.nextSibling );通过将target元素包装在jQuery对象中,相同的任务变得更加简单:
// Inserting a new element after another with jQuery.
var target = document.getElementById( "target" );
var newElement = document.createElement( "div" );
$( target ).after( newElement );在大多数情况下,这些细节只是站在你和你的目标之间的“陷阱”。
当使用CSS选择器调用jQuery函数时,它将返回一个包含与此选择器匹配的元素的jQuery对象。例如,写作:
// Selecting all <h1> tags.
var headings = $( "h1" );headings现在包含一个jQuery元素的所有的<h1>标签已经在页面上。这可以通过检查以下.length属性来验证headings:
// Viewing the number of <h1> tags on the page.
var headings = $( "h1" );
alert( headings.length );如果页面有多个<h1>标签,则该数字将大于1。如果页面没有<h1>标签,.length属性将为零。检查.length属性是确保选择器成功匹配一个或多个元素的常用方法。
如果目标是仅选择第一个标题元素,则需要另一个步骤。有很多方法可以做到这一点,但最直接的就是.eq()功能。
// Selecting only the first <h1> element on the page (in a jQuery object)
var headings = $( "h1" );
var firstHeading = headings.eq( 0 );现在firstHeading是一个仅包含<h1>页面上第一个元素的jQuery对象。因为firstHeading是一个jQuery对象,它有一些有用的方法,如.html()和.after()。jQuery还有一个命名方法.get()提供了一个相关的功能。而不是返回一个包含jQuery的DOM元素,它返回DOM元素本身。
// Selecting only the first <h1> element on the page.
var firstHeadingElem = $( "h1" ).get( 0 );或者,因为jQuery对象是“类似数组”,它通过括号支持数组下标:
// Selecting only the first <h1> element on the page (alternate approach).
var firstHeadingElem = $( "h1" )[ 0 ];在任一情况下,都firstHeadingElem包含本机DOM元素。这意味着它有DOM属性,如.innerHTML等方法.appendChild(),但不是 jQuery的方法,如.html()或.after()。这个firstHeadingElem元素比较难使用,但有些情况需要它。一个这样的例子是进行比较。
===关于这种“包装”行为的一个重要细节是每个包装的对象是唯一的。即使使用相同的选择器创建对象或包含对完全相同的DOM元素的引用,这一点也是如此。
// Creating two jQuery objects for the same element.
var logo1 = $( "#logo" );
var logo2 = $( "#logo" );虽然logo1并logo2以相同的方式创建(并包装相同的DOM元素),但它们不是相同的对象。例如:
// Comparing jQuery objects.
alert( $( "#logo" ) === $( "#logo" ) ); // alerts "false"但是,这两个对象都包含相同的DOM元素。该.get()方法对于测试两个jQuery对象是否具有相同的DOM元素是有用的。
// Comparing DOM elements.
var logo1 = $( "#logo" );
var logo1Elem = logo1.get( 0 );
var logo2 = $( "#logo" );
var logo2Elem = logo2.get( 0 );
alert( logo1Elem === logo2Elem ); // alerts "true"许多开发人员$为包含jQuery对象的变量名称前缀a 以帮助区分。这种做法没有任何魔法 - 它只是帮助一些人追踪不同变量的含义。以前的例子可以重新写成遵循这个约定:
// Comparing DOM elements (with more readable variable names).
var $logo1 = $( "#logo" );
var logo1 = $logo1.get( 0 );
var $logo2 = $( "#logo" );
var logo2 = $logo2.get( 0 );
alert( logo1 === logo2 ); // alerts "true"该代码与上述示例的功能相同,但是读取更清楚一些。
不管使用的命名规则如何,使jQuery对象和本机DOM元素之间的区别非常重要。本机DOM方法和属性不存在于jQuery对象上,反之亦然。错误消息,如“event.target.closest不是一个函数”和“TypeError:Object [object Object]没有方法'setAttribute'”表示存在这个常见的错误。
给定一个jQuery对象,其中包含页面上的所有段落元素:
// Selecting all <p> elements on the page.
var allParagraphs = $( "p" );...可能会期望随着<p>元素被添加和从文档中删除,内容将随着时间的推移而增长和缩小。jQuery对象不以这种方式表现。包含在jQuery对象中的元素集将不会改变,除非明确修改。这意味着该集合不是“直播” - 它不会随着文档的更改而自动更新。如果文档自创建jQuery对象以来可能已经更改,那么应该通过创建一个新的集合来更新该集合。它可以像重新运行同一个选择器一样简单:
// Updating the selection.
allParagraphs = $( "p" );虽然DOM元素提供了创建交互式网页所需的所有功能,但它们可能是一个麻烦的工作。jQuery对象包装这些元素,以平滑这种体验,使常见任务变得容易。当使用jQuery创建或选择元素时,结果将始终包含在一个新的jQuery对象中。如果情况需要原生DOM元素,则可以通过.get()方法和/或数组样式的下标访问它们。