如何将“元数据”附加到DOM节点?

时间:2010-01-09 14:48:29

标签: javascript jquery html

有时我想将某种元数据附加到HTML节点上,我想知道,最好的方法是什么。

我可以想象以下内容:

  • 非标准属性:<div myattr1="myvalue1" myattr2="myvalue2" >(中断验证)
  • 重用现有属性<div class="myattr1-myvalue2-myattr2-myvalue2">(需要解析和某种程度的转义)

这两种解决方案都非常难看!

有没有办法更优雅地做到这一点?我已经在使用jQuery,所以任何好的Javascript解决方案,如果有的话,也会受到赞赏。

6 个答案:

答案 0 :(得分:37)

HTML5引入了custom data attributes的概念,任何人都可以创建这个概念,以便将自定义隐藏数据附加到元素以用于编写脚本。只需使用data-前缀(例如data-myattr1data-myattr2)创建属性,然后将其填入您的数据。

<div data-myattr1="myvalue1" data-myattr2="myvalue2">Content</div>

这个解决方案的好处在于它已经适用于所有主流浏览器;它们都将解析未知属性,并在DOM中公开它们以供JavaScript访问。 HTML5为访问它们添加了一些便利机制,但尚未实现,但您现在可以使用标准getAttribute来访问它们。并且HTML5中允许它们的事实意味着您的代码将验证,只要您愿意使用草案标准而不是接受标准(我不相信data-属性特别有争议但是,如果将它们从标准中移除,我会感到惊讶。

这对XHTML中的命名空间属性的优势是IE不支持XHTML,因此您必须实现假装使用命名空间属性但实际上只使用名称中带有:的无效属性的东西,IE是如何解析它们的。它比使用class更好,因为将大量数据放入class属性会使它过载很多,并且需要进行额外的解析来提取不同的数据。而且它比构建自己的更好(它可以在当前的浏览器中使用),因为它定义为前缀为data-的这些属性是用于编写脚本的私有数据,因此您的代码将在HTML5中验证并赢得不会与未来的标准发生冲突。

另一种将自定义数据添加到HTML的鲜为人知的技术,即使在HTML 4中也是有效的,就是添加scripttype个元素以及text/javascript以外的其他属性(或者一个其中一些可用于指定JavaScript的类型)这些脚本块将被不知道如何使用它们的浏览器忽略,您可以通过DOM访问它们并使用它们执行您想要的操作。 HTML5 explicitly discusses this usage,但在旧版本中没有任何东西可以使它无效,据我所知,它适用于所有现代浏览器。例如,如果您想使用CSV来定义数据表:

<div>
  <script type="text/csv;header=present">
    id,myattr1,myattr2
    something,1,2
    another,2,4
  </script>
  Content
</div>

这是SVG Web允许在HTML中嵌入SVG的技术,如果浏览器不支持本机SVG,则通过Flash进行模拟。目前,即使支持SVG(Firefox,Safari,Chrome,Opera)的浏览器也不支持直接内联在HTML中,它们只支持在XHTML中直接内联(因为SVG元素位于不同的命名空间中)。 SVG Web允许您使用脚本标记将SVG内联到HTML中,然后将这些元素转换为适当的命名空间并将它们添加到DOM中,以便将它们呈现为XHTML。在不支持SVG的浏览器中,它还使用Flash模拟元素的功能。

答案 1 :(得分:11)

如果没有必要在标记中存储属性,那么一个很好的解决方案是jQuery的data函数:http://docs.jquery.com/Core/data

答案 2 :(得分:5)

一个可能与您的要求不完全匹配的可能解决方案是使用类作为“元数据存储库”,使用方法根据元素的id获取/设置数据。

var metadataRepository = function(){
    this.elements = [];

    this.set = function(id,key,value){ 
        this.elements[id][key] = value;
    }

    this.get = function(id,key){
        if (typeof(this.elements[id]) == "undefined"){
            return null;
        }
        if (key){
            return (this.elements[id][key] != "undefined") ? this.elements[id][key] : null;
        } else {
            return this.elements[id];   
        }
    }

}

var myMR = new metadataRepository();

myMR.set("myDiv1","attr1",232442);
myMR.set("myDiv2","attr1",{"id":23,"name":"testName"});

...

myMR.get("myDiv1","attr1");  //Returns only attr1
myMR.get("myDiv2");   //Returns all attributes

答案 3 :(得分:3)

假设XHTML,只需为您自己的元数据引入一个新的命名空间。这样,您可以使用任意名称在自己的命名空间中拥有属性,并且它们不会与任何验证冲突。

基本上你只需要添加

xmlns:myns="http://www.example.com/URI/to/myNamespaceDeclaration"

到根节点,然后你可以拥有诸如

之类的节点
<p myns:type="important">I'm a paragraph.</p>

在那个根目录下的任何地方。这基本上是命名空间的全部目的,允许开发人员将任意数据作为层添加到整个模型中。

修改

快速注释,class属性现在被microformats用于元数据标记目的。您可能需要查看上面的链接,看看是否有人已经发明了您想要提出的方向盘:)

答案 4 :(得分:2)

WeakMap可能会做到这一点。它是一个类似于地图的数据结构,其中键是对象,值是任意值。

const div = document.createElement("div")
const metadata = new WeakMap()
metadata.set(div, "div metadata")
metadata.get(div) // "div metadata"

答案 5 :(得分:0)

如果你正在使用xhtml,你可以调整你的DTD,以便你的额外属性验证。

如果您使用的是html5,则可以使用data-foobarbaz属性。