关于javascript:如何为某些HTML标记存储任意数据

How to store arbitrary data for some HTML tags

我正在制作一个由javascript提供一些交互的页面。仅作为示例:发送AJAX请求以获取文章内容然后在div中显示该数据的链接。显然在这个例子中,我需要每个链接来存储额外的信息:文章的ID。我一直在处理它的方式是将这些信息放在href链接中:

1
 

然后我使用jQuery来查找a.article元素并附加相应的事件处理程序。 (不要太在意这里的可用性或语义,这只是一个例子)

无论如何,这种方法有效,但它有点味道,根本不可扩展(如果click函数有多个参数会发生什么?如果其中一些参数是可选的,会怎样?)

显而易见的答案是在元素上使用属性。我的意思是,这就是他们的目的,对吗? (的种类)。

1
 

在我最近的一个问题中,我问这个方法是否有效,结果是没有定义我自己的DTD(我没有),那么不,它是无效的或可靠的。一个常见的反应是将数据放入class属性(虽然这可能是因为我选择不当的例子),但对我来说,这更令人闻到。是的,它在技术上是有效的,但它不是一个很好的解决方案。

我过去使用的另一种方法是实际生成一些JS并将其插入到标记的页面中,创建一个与该对象关联的结构。

1
2
3
4
5
6
7
8
9
10
var myData = {
    link0 : {
        articleId : 5,
        target : '#showMessage'
        // etc...
    },
    link1 : {
        articleId : 13
    }
};

但这可能是维持对接的真正痛苦,而且通常只是非常混乱。

那么,为了解决这个问题,你如何为HTML标签存储任意信息?


您使用的是哪个版本的HTML?

在HTML 5中,具有以数据为前缀的自定义属性是完全有效的,例如,

1
 

在XHTML中,这不是真正有效的。如果您处于XHTML 1.1模式,浏览器可能会抱怨它,但在1.0模式下,大多数浏览器都会默默地忽略它。

如果我是你,我会遵循基于脚本的方法。你可以在服务器端自动生成它,这样就不会让后面的人感到痛苦。


如果您已经在使用jQuery,那么您应该利用"data"方法,这是使用jQuery在dom元素上存储任意数据的推荐方法。

存储东西:

1
$('#myElId').data('nameYourData', { foo: 'bar' });

要检索数据:

1
var myData = $('#myElId').data('nameYourData');

这就是它的全部内容,但请查看jQuery文档以获取更多信息/示例。


换句话说,我个人不会使用它,但它可以工作(确保你的JSON有效,因为eval()是危险的)。

1
2
3
4
5
6
7
    <span style="display: none;">{"id": 1,"title":"Something"}</span>
    Text of Link


// javascript
var article = document.getElementsByClassName("article")[0];
var data = eval(article.childNodes[0].innerHTML);


任意属性无效,但在现代浏览器中完全可靠。如果您通过javascript设置属性,那么您也不必担心验证。

另一种方法是在javascript中设置属性。 jQuery有一个很好的实用方法,只是为了这个目的,或者你可以自己推出。


几乎所有可能的浏览器都可以使用的hack是使用这样的开放类:;

这对于纯粹主义者来说并不是那么优雅,但它得到普遍支持,符合标准,并且非常容易操作。这似乎是最好的方法。如果您serialize,修改,复制您的标签或做其他任何事情,data将保持附加,复制等。

唯一的问题是你不能以这种方式存储不可序列化的对象,如果你把那些非常庞大的东西放在那里可能会有限制。

第二种方法是使用假属性,如:

这更优雅,但打破标准,我不是100%肯定支持。许多浏览器都完全支持它,我认为IE6支持JS访问但不支持CSS selectors(这在这里并不重要),也许某些浏览器会完全混淆,你需要检查它。

做序贯化和反序列化等有趣的事情会更加危险。

使用ids到纯JS哈希主要起作用,除非您尝试复制标记。如果您有tag ,请通过标准JS方法复制它,然后尝试修改附加到一个副本的data,另一个副本将被修改。

如果您不复制tag或使用只读数据,这不是问题。如果您复制tag并且修改了它们,则需要手动处理。


使用jquery,

存储:$('#element_id').data('extra_tag', 'extra_info');

检索:$('#element_id').data('extra_tag');


您可以使用隐藏的输入标记。我在w3.org上没有得到任何验证错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="content-type" />
    Hello
  </head>
  <body>
   
     
        <input style="display: none" name="articleid" type="hidden" value="5" />
     
   
  </body>
</html>

使用jQuery,你会得到类似(未经测试)的文章ID:

1
$('.article input[name=articleid]').val();

但如果这是一个选项我会推荐HTML5。


我知道你现在正在使用jQuery,但如果你内联定义了onclick处理程序会怎样。然后你可以这样做:

1
     Article 5

作为jQuery用户,我会使用Metadata插件。 HTML看起来干净,验证,并且您可以嵌入任何可以使用JSON表示法描述的内容。


为什么不利用已有的有意义的数据,而不是添加任意数据?

即使用,然后您可以通过编程方式获取页面上的所有文章链接(通过类名称)和文章ID(匹配this.href的正则表达式/articles\/(\d+)/)。


所以应该有四种选择:

  • 将数据放在id属性中。
  • 将数据放在任意属性中
  • 将数据放在class属性中
  • 将您的数据放在另一个标签中
  • http://www.shanison.com/?p=321


    我主张使用"rel"属性。 XHTML验证,很少使用属性本身,并且有效地检索数据。


    这是个好建议。感谢@Prestaul

    If you are using jQuery already then you should leverage the"data"
    method which is the recommended method for storing arbitrary data on a
    dom element with jQuery.

    这是真的,但是如果你想在普通的HTML中存储任意数据呢?这是另一种选择......

    1
    <input type="hidden" name="whatever" value="foobar"/>

    将数据放在隐藏输入元素的名称和值属性中。如果服务器生成HTML(即PHP脚本或其他),这可能很有用,并且您的JavaScript代码稍后将使用此信息。

    诚然,不是最干净的,但它是另一种选择。它与所有人兼容
    浏览器并且是有效的XHTML。您不应该使用自定义属性,也不应该使用带有'data-'前缀的属性,因为它可能不适用于所有浏览器。此外,您的文档不会通过W3C验证。


    您可以使用随机元素()自己的属性的数据前缀,但这仅在HTML5中有效。因此浏览器可能会抱怨有效性。

    您还可以使用Data goes here...标签。但是这种方式你不能使用属性函数,如果关闭css和js,这也不是一个真正的解决方案。

    但我个人更喜欢以下内容:

    1
    <input type="hidden" title="Your key..." value="Your value..." />

    在所有情况下,输入都将被隐藏,属性完全有效,如果它在

    标签内,它将不会被发送,因为它没有任何名称,对吧?
    最重要的是,这些属性非常容易记住,而且代码看起来很简单易懂。您甚至可以在其中添加ID属性,因此您也可以使用JavaScript轻松访问它,并使用input.title; input.value访问键值对。


    一种可能性可能是:

    • 创建一个新的div来保存所有扩展/任意数据
    • 做一些事情来确保这个div是不可见的(例如CSS加上div的class属性)
    • 将扩展/任意数据放在[X] HTML标记内(例如,作为表格单元格中的文本,或者您可能喜欢的任何其他内容)在此不可见的div中

    另一种方法是使用以下语法将键:值对存储为简单类:

    1
    ...

    这是有效的,可以使用jQuery选择器或自定义函数轻松检索。


    在html中,我们可以在属性名称之前存储带有前缀'data-'的自定义属性

    <5233>。
    检查文档

    我们可以使用此属性使用jQuery动态设置和获取属性,如:
    如果我们有像这样的p标签

    This animal is a dog.

    然后为上面的标签创建一个名为'breed'的属性,我们可以写:

    $('#animal').attr('data-breed', 'pug');

    要随时检索数据,我们可以写:

    var breedtype = $('#animal').data('breed');


    这就是我如何ajax页面...这是一个非常简单的方法...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        function ajax_urls() {
           var objApps= ['ads','user'];
            $("a.ajx").each(function(){
                   var url = $(this).attr('href');
                   for ( var i=0;i< objApps.length;i++ ) {
                       if (url.indexOf("/"+objApps[i]+"/")>-1) {
                          $(this).attr("href",url.replace("/"+objApps[i]+"/","/"+objApps[i]+"/#p="));
                       }
                   }
               });
    }

    这是如何工作的,它基本上查看所有具有类'ajx'的URL,它替换了一个关键字并添加#符号......所以如果关闭js,那么网址将按照通常的方式行事......所有"应用程序"(网站的每个部分)都有自己的关键字......所以我需要做的就是添加到上面的js数组中以添加更多页面...

    例如,我的当前设置设置为:

    1
     var objApps= ['ads','user'];

    所以,如果我有一个网址,如:

    www.domain.com/ads/3923/bla/dada/bla

    js脚本将替换/ ads / part,以便我的URL最终成为

    www.domain.com/ads/#p=3923/bla/dada/bla

    然后我使用jquery bbq插件来相应地加载页面...

    http://benalman.com/projects/jquery-bbq-plugin/


    我发现元数据插件是一个很好的解决方案,可以解决使用html标签存储任意数据的问题,这样可以很容易地检索和使用jQuery。

    重要提示:您包含的实际文件只有5 kb而不是37 kb(这是完整下载包的大小)

    以下是用于存储我在生成Google分析跟踪事件时使用的值的示例(注意:data.label和data.value恰好是可选参数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $(function () {
        $.each($(".ga-event"), function (index, value) {
            $(value).click(function () {
                var data = $(value).metadata();
                if (data.label && data.value) {
                    _gaq.push(['_trackEvent', data.category, data.action, data.label, data.value]);
                } else if (data.label) {
                    _gaq.push(['_trackEvent', data.category, data.action, data.label]);
                } else {
                    _gaq.push(['_trackEvent', data.category, data.action]);
                }
            });
        });
    });

    <input class="ga-event {category:'button', action:'click', label:'test', value:99}" type="button" value="Test"/>


    在我以前的雇主,我们一直使用自定义HTML标签来保存有关表单元素的信息。问题:我们知道用户被迫使用IE。

    它当时对FireFox来说效果不佳。我不知道FireFox是否改变了这一点,但请注意,读者的浏览器可能会也可能不支持将自己的属性添加到HTML元素中。

    如果您可以控制您的阅读器使用的浏览器(即公司的内部Web小程序),那么请尝试一下。它有什么害处,对吗?


    只要你的实际工作是在服务器端完成的,为什么你还需要输出中的html标签中的自定义信息?您需要知道的在服务器上的所有信息都是使用您的自定义信息的任何类型的结构列表的索引。我想你想把信息存放在错误的地方。

    无论多么令人遗憾的是,我会认识到,在许多情况下,正确的解决方案并不是正确的解决方案。在这种情况下,我强烈建议生成一些javascript来保存额外的信息。

    许多年后:

    这个问题发布大约三年之前,随着html 5的出现,data-...属性成为一个有效的选项,所以真相已经转移,我给出的原始答案已不再适用。现在我建议使用数据属性。

    1
    2
    3
    4
        let anchors = document.getElementsByTagName('a');
        for (let anchor of anchors) {
            let articleId = anchor.dataset.articleId;
        }