自定义属性 – 是或不是?

最近,我一直在阅读越来越多关于在HTML标记中使用自定义属性的人,主要是为了embedded一些额外的数据位以用于JavaScript代码。

我希望收集一些关于是否使用自定义属性是一个好的做法,也是一些替代方法的反馈。

它似乎可以真正简化服务器端和客户端代码,但它也不符合W3C。

我们应该在我们的networking应用程序中使用自定义HTML属性吗? 为什么或者为什么不?

对于那些认为自定义属性是好东西的人来说:使用它们时要注意些什么?

对于那些认为自定义属性是坏事的人:你用什么办法来完成类似的事情?

更新:我最感兴趣的是各种方法背后的推理 ,以及为什么一种方法比另一种好。 我想我们都可以拿出4-5种不同的方式来完成同样的事情。 (隐藏的元素,内联脚本,额外的类,来自ID的parsing信息等)。

更新2:看来,HTML 5的data-属性function在这里有很多的支持(我倾向于同意,它看起来像一个坚实的select)。 到目前为止,我还没有看到这个build议的反驳方式。 是否有任何问题/陷阱担心使用这种方法? 还是仅仅是当前W3C规范的“无害”无效?

HTML 5显式允许以data开头的自定义属性。 所以,例如, <p data-date-changed="Jan 24 5:23 pm">Hello</p>有效。 由于它是由一个标准正式支持,我认为这是自定义属性的最佳select。 而且它不要求你用黑客来重载其他属性,所以你的HTML可以保持语义。

资料来源: http : //www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes

这是我最近使用的一种技术:

 <div id="someelement"> <!-- { someRandomData: {a:1,b:2}, someString: "Foo" } --> <div>... other regular content...</div> </div> 

注释对象绑定到父元素(即#someelement)。

这是parsing器: http : //pastie.org/511358

要获取任何特定元素的数据,只需调用parseData引用该元素作为唯一parameter passing:

 var myElem = document.getElementById('someelement'); var data = parseData( myElem ); data.someRandomData.a; // <= Access the object staight away 

它可以比这更简洁:

 <li id="foo"> <!--{specialID:245}--> ... content ... </li> 

访问它:

 parseData( document.getElementById('foo') ).specialID; // <= 245 

使用它的唯一缺点是它不能与自闭元素(比如<img/> )一起使用,因为注释必须位于要被视为元素数据的元素内。


编辑

这种技术的显着好处:

  • 易于实施
  • 不会使HTML / XHTML无效
  • 易于使用/理解(基本的JSON表示法)
  • 比大多数替代品都不显眼且语义清晰

这里是parsing器代码(从上面的http://pastie.org/511358超链接复制,以防在pastie.org上无法使用):

 var parseData = (function(){ var getAllComments = function(context) { var ret = [], node = context.firstChild; if (!node) { return ret; } do { if (node.nodeType === 8) { ret[ret.length] = node; } if (node.nodeType === 1) { ret = ret.concat( getAllComments(node) ); } } while( node = node.nextSibling ); return ret; }, cache = [0], expando = 'data' + +new Date(), data = function(node) { var cacheIndex = node[expando], nextCacheIndex = cache.length; if(!cacheIndex) { cacheIndex = node[expando] = nextCacheIndex; cache[cacheIndex] = {}; } return cache[cacheIndex]; }; return function(context) { context = context || document.documentElement; if ( data(context) && data(context).commentJSON ) { return data(context).commentJSON; } var comments = getAllComments(context), len = comments.length, comment, cData; while (len--) { comment = comments[len]; cData = comment.data.replace(/\n|\r\n/g, ''); if ( /^\s*?\{.+\}\s*?$/.test(cData) ) { try { data(comment.parentNode).commentJSON = (new Function('return ' + cData + ';'))(); } catch(e) {} } } return data(context).commentJSON || true; }; })(); 

如果您为页面指定模式,则可以创build任何属性。

例如:

加这个

 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:addthis="http://www.addthis.com/help/api-spec"> ... <a addthis:title="" addthis:url="" ...> 

Facebook (甚至标签)

 <html xmlns:og="http://opengraphprotocol.org/schema/" xmlns:fb="http://www.facebook.com/2008/fbml"> ... <fb:like href="http://developers.facebook.com/" width="450" height="80"/> 

避免使用自定义属性的最简单方法是使用现有的属性。

使用有意义的相关类名。
例如,执行如下操作: type='book'type='cd' ,以表示书籍和CD。 类表示什么是IS要好得多。

例如class='book'

过去我使用过自定义属性,但是老实说,如果你使用语义上有意义的方式来使用现有的属性,实际上并不需要它们。

举一个更具体的例子,假设你有一个网站给不同types的商店提供链接。 您可以使用以下内容:

 <a href='wherever.html' id='bookstore12' class='book store'>Molly's books</a> <a href='whereverelse.html' id='cdstore3' class='cd store'>James' Music</a> 

CSS的样式可以使用类如:

 .store { } .cd.store { } .book.store { } 

在上面的例子中,我们看到两者都是商店的链接(而不是网站上其他不相关的链接),一个是CD商店,另一个是书店。

在dom中embedded数据并为jQuery使用元数据 。

所有优秀的插件都支持元数据插件(允许每个标签选项)。

它还允许无限复杂的数据/数据结构以及键值对。

 <li class="someclass {'some': 'random,'json':'data'} anotherclass">...</li> 

要么

 <li class="someclass" data="{'some':'random', 'json': 'data'}">...</li> 

要么

 <li class="someclass"><script type="data">{"some":"random","json":"data"}</script> ...</li> 

然后得到这样的数据:

 var data = $('li.someclass').metadata(); if ( data.some && data.some == 'random' ) alert('It Worked!'); 

我认为在不破坏任何东西或扩展名称空间的情况下使用现有的XHTML特性没有问题。 我们来看一个小例子:

 <div id="some_content"> <p>Hi!</p> </div> 

如何在没有附加属性的情况下向some_content添加附加信息? 如何添加另一个标签,如下所示?

 <div id="some_content"> <div id="some_content_extended" class="hidden"><p>Some alternative content.</p></div> <p>Hi!</p> </div> 

它通过一个明确定义的ID /扩展名“_extended”来保持你的select和它在层次结构中的位置。 我经常和jQuery一起使用这种方法,而没有实际使用Ajax技术。

我没有使用自定义属性,因为我输出的是XHTML,因为我希望数据可以被第三方软件机器读取(尽pipe如果我愿意,我可以扩展XHTML模式)。

作为自定义属性的替代,大多数情况下,我发现id和class属性(例如其他答案中提到的)就足够了。

另外,请考虑这一点:

  • 如果额外的数据是可读的和机器可读的,那么它需要使用(可见)HTML标签和文本进行编码,而不是作为自定义属性进行编码。

  • 如果它不需要人类可读,那么也许可以使用不可见的 HTML标签和文本进行编码。

有些人做了一个例外:他们允许自定义属性,在运行时通过客户端的Javascript添加到DOM。 他们认为这是可以的:因为自定义属性只在运行时被添加到DOM,所以HTML不包含自定义属性。

不仅如此。 尝试这样的事情,而不是:

 <div id="foo"/> <script type="text/javascript"> document.getElementById('foo').myProperty = 'W00 H00! I can add JS properties to DOM nodes without using custom attributes!'; </script> 

我们已经制作了一个基于networking的编辑器,它可以理解HTML的一个子集 – 一个非常严格的子集(几乎被邮件客户端理解)。 我们需要在数据库中expression诸如<td width="@INSWIDTH_42@">的东西,但是我们不能在DOM中使用它,否则编辑器运行的浏览器就会吓倒(或者更可能比它可能会超出自定义属性)。 我们想要拖放,所以纯粹把它放在DOM中,就像jQuery的.data() (额外的数据没有被正确复制)一样。 我们可能还需要额外的数据来搭配.html() 。 最后,我们在编辑过程中决定使用<td width="1234" rs-width="@INSWIDTH_42@"> ,然后当我们把所有的东西都POST时,我们移除width并做一个正则expression式search-and-destroy s/rs-width=/width=/g

起初,写这个大部分的人是这个问题上的validation纳粹,并试图避免我们的自定义属性,但最终默认没有其他东西似乎适用于我们所有的要求。 当他意识到自定义属性永远不会出现在电子邮件中时,它帮助了我们在class考虑编码额外的数据,但决定这将是两个邪恶中的更大的一个。

就我个人而言,我更喜欢把事情弄清楚,并通过validation等等,但作为一名公司员工,我必须记住,我的主要责任是推进公司的事业(尽可能快地赚更多的钱),而不是我自私的渴望技术纯度。 工具应该为我们工作; 不是我们为他们。

我知道人们反对,但我想出了一个超级短的解决scheme。 如果你想使用像“我”这样的自定义属性,例如:

 <a href="test.html" mine-one="great" mine-two="awesome">Test</a> 

然后你可以像jquery.data()那样运行这个代码来获取对象。

 var custom_props = {} ; $.each($(".selector")[0].attributes, function(i,x) { if (this.specified && x.name.indexOf("mine-") !== -1) self.new_settings[x.name.replace("modal-","")] = x.value; }); 

规范: 根据属性“DecimalSeparator”和“ThousandsSeparator”,使用JavaScript创build一个ASP.NET TextBox控件,该控件将其文本dynamic自动设置为数字。

将这些属性从控件转移到JavaScript的一种方法是让控件呈现自定义属性:

 <input type="text" id="" decimalseparator="." thousandsseparator="," /> 

自定义属性很容易通过JavaScript访问。 虽然使用具有自定义属性的元素的页面不会被validation ,但该页面的呈现不会受到影响。

当我想要将诸如string和整数之类的简单types关联到用于JavaScript的HTML元素时,我使用这种方法。 如果我想使HTML元素更容易识别,我将使用id属性。

我一直使用自定义字段例如<ai =“”….然后引用我与jquery。 无效的HTML,是的。 它运作良好,是的。

对于复杂的networking应用程序,我放弃自定义属性。

对于更多面向公众的页面,我使用“rel”属性,并将所有数据以JSON格式转储,然后使用MooTools或jQuery对其进行解码:

 <a rel="{color:red, awesome:true, food: tacos}">blah</a> 

我试图最近坚持使用HTML 5数据属性来“准备”,但它还没有自然而然地出现。

在我看来,自定义属性不应该被使用,因为它们不会被validation。 除此之外,您可以为单个元素定义许多类,例如:

 <div class='class1 class2 class3'> Lorem ipsum </div>