【问题标题】:Retrieving HTML attribute values "the DOM 0 way"检索 HTML 属性值“DOM 0 方式”
【发布时间】:2012-04-23 21:53:48
【问题描述】:

jQuery 有一个attr() 方法,用于检索给定 HTML 属性的值。例如:

var foo = document.getElementById("foo");
$(foo).attr("id");

但是,就性能而言,这并不是最优的,因为必须创建一个 jQuery 对象才能调用attr() 方法。这表现更好:foo.id

因此,理想情况下,我们希望避免使用attr()。但是,我们可以这样做(对于任何属性)吗?我相信foo.idfoo.value 是“安全的”(跨浏览器),但我记得foo.href 有问题。

以下是我希望能够“直接”检索的各种属性的列表:

对于任何元素:foo.idfoo.name
对于主播:foo.hreffoo.targetfoo.rel
对于图像、对象、iframe:foo.srcfoo.widthfoo.height
对于表单元素:foo.checkedfoo.selectedfoo.disabledfoo.readonlyfoo.typefoo.valuefoo.action

所以问题是:上面的表达式是跨浏览器的吗?我可以安全地使用它们吗?

链接到一篇研究这个问题的文章也很好。

编辑(根据答案):粗体字不安全!

【问题讨论】:

    标签: javascript html cross-browser


    【解决方案1】:

    jQuery 的 attr() 方法命名有误,文档记录不充分,并且隐藏了一个非常重要的区别:属性和属性之间的区别,许多 Web 开发人员似乎不太了解这一点,尤其是那些JavaScript 的介绍来自 jQuery。

    如果您没有进一步阅读,请把它拿走:您几乎永远不需要使用属性。使用相应的属性几乎总是更好。事实上,这就是 jQuery 的 attr() 方法 通常做 在 1.6 版之前所做的。

    在处理 HTML DOM 时使用属性并避免使用 getAttribute()setAttribute() 的原因:

    • IE 的实现已损坏。在较旧版本和较新版本的 quirks 模式中,属性直接映射到属性,这与 DOM 标准相反。这样做的一个后果是事件处理程序属性(onclick 等)在 IE 中被彻底破坏。 始终为事件处理程序使用属性。这样做的另一个后果是,这些模式和版本中的 IE 要求您使用getAttribute("className") 而不是getAttribute("class") 来检索class 属性。
    • 属性(大部分)一致地跨浏览器实现
    • 某些属性和属性之间的关系并不像您想象的那样。某些属性,特别是 <input> 元素的 value 属性,与同名的属性没有关联:一旦输入的值已更改(由用户或脚本更改),获取或设置 @ 987654333@ 属性无效。相反,value 属性与defaultValue 属性同步。
    • 属性通常更方便。例如,考虑布尔属性,例如 checked:这在 DOM 中表示为布尔值 checked 属性,而关于如何使用属性设置复选框的选中性则很混乱。是removeAttribute("checked")吗? setAttribute("checked", "")? setAttribute("checked", false)?都是错误的,因为checked 属性实际上映射到defaultChecked 属性。

    在某些情况下可能需要使用属性。例如,<a> 元素的 href 属性始终报告完全限定的 URL,而 getAttribute("href") 将逐字返回 HTML href 属性中指定的字符串。当然,在 IE 中除外。 jQuery 的attr() 确实试图规范这种不一致。

    有关此主题的更多信息:http://reference.sitepoint.com/javascript/Element/setAttribute,以及来自 MSDN 的:http://msdn.microsoft.com/en-us/library/dd347148%28v=vs.85%29.aspx

    最后,我强烈建议尽可能直接使用 DOM 属性,而不是使用 jQuery 的 attr() 方法,但是您需要注意它处理的特殊情况(例如 href)。在您提到的属性中,所有这些属性都可以完全安全地跨浏览器使用,但以下情况除外:

    • foo.hreffoo.src(存在类似问题)如上所述。
    • foo.type 只能在 <input> 元素添加到 DOM 之前设置。
    • foo.selected(其中 foo 是 <option> 元素)显然在旧版本的 Safari 中存在错误,如另一个答案中所述。

    【讨论】:

    • 是的,我知道那个属性/属性的区别。 :) 但是如果我使用“DOM HTML 元素属性”这个术语,我担心人们不会理解。术语“属性”是不正确的,但它被广泛使用并理解为是指基于 HTML 源代码中的 HTML 属性创建的某些 DOM 元素属性。
    • 另外,我相信 IE9 beta 解决了 href 问题。 foo.href 返回完整的 URL,而 foo.attributes.href.valuefoo.getAttribute("href") 返回源代码中 href 属性的值。
    • @Šime Vidas:我喜欢利用一切机会指出 DOM 属性和属性之间的区别。对不起,如果这对你来说是不必要的。我现在添加了一些关于您询问的属性的信息。
    • @yc:哇。这会破坏各种东西,所以如果他们回溯到那我不会感到惊讶,但我希望不会。 Resig 说得对,这是一个本质性的改变。感谢您的链接。
    • “我们认为这将有可能打破现状……” 年度轻描淡写的新提名。
    【解决方案2】:

    看看 jQuery 是如何处理它的:

    • href、src 和 style 属性需要特殊处理。
    • Safari 在访问 select 元素上的“selected”属性时存在错误。如果访问“selected”属性,Safari 需要特殊处理。

    查看jQuery source,并搜索此行以了解我所说的“特殊待遇”是什么意思:
    attr: function( elem, name, value, pass ) {

    简而言之:我认为对列出的大多数属性执行您想要的操作是安全的,除了上面显示的属性。


    为了简单起见,您可以这样做:

    $foo = $("#foo");
    console.log( $foo.attr("id"), $foo.attr("style"), $foo.attr("href") );
    只制作了 1 个 jQuery 对象,您不必担心手动处理任何事情。

    【讨论】:

    • OK,总结一下:href和src需要attr()。知道了。 (样式属性搞砸了,所以我无论如何都不想检索它。)
    • 缓存 jQuery 对象(var $foo = $("#foo"); 是页面加载的好习惯。但是,在事件处理程序内部,我们有 this 值,它指向与事件相关的 DOM 元素。在此在这种情况下,创建$(this) 是一种性能损失,并且能够通过“DOM 0 方式”检索属性值来避免它是一种很好的技术。
    • @ŠimeVidas 您也可以对事件处理程序中的对象执行相同的操作,除非它们是动态变化的。只需将它们放入 each 循环并在 DOM 加载时保存 $this 一次。有点低于标准,但可能对性能有所帮助。如果有足够多的元素(或足够数量的事件调用)让您担心性能,另一种提高性能的方法是将事件附加到父事件并使用事件的目标。当然,如果你正在做的事情有保证(例如,构建一个会被大量使用的小部件或应用程序),你总是可以用纯 JS 手工制作所有东西。
    【解决方案3】:

    1) 我真的不认为性能是一个问题。我的猜测是'foo'只是一个指针,而不是占用内存空间的对象。不过不确定。

    2) 您根本不必创建变量 foo。 $("#foo").attr("id") 就可以了。

    3) DOM 有几种访问属性的方法。尝试 .getAttribute("name")、.setAttribute("name") 和 .removeAttribute("name")

    【讨论】:

    • 1) this.id$(this).attr("id") 快 10 倍以上 3) 我相信这些方法在 IE6 和 IE7 中不起作用
    • getAttribute() 在 IE6 和 IE7 中应该可以正常工作。问题是跨浏览器不一致。
    • IE6 应该支持所有这些方法。它们是 DOM1 的一部分。
    • 但是好像有问题:en.wikipedia.org/wiki/…
    • @simshaun, @jeff:IE 6 和 7 的属性实现完全损坏。看我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 2011-04-16
    • 1970-01-01
    相关资源
    最近更新 更多