提问人:TM. 提问时间:6/14/2009 最后编辑:surfmuggleTM. 更新时间:12/2/2022 访问量:64225
自定义属性 - 是还是不是?
Custom attributes - Yea or nay?
问:
最近,我读到越来越多的关于人们在他们的 HTML 标签中使用自定义属性的信息,主要是为了嵌入一些额外的数据以在 javascript 代码中使用。
我希望收集一些关于使用自定义属性是否是一种好做法的反馈,以及一些替代方案。
它似乎可以真正简化服务器端和客户端代码,但它也不符合 W3C 标准。
我们是否应该在 Web 应用程序中使用自定义 HTML 属性?为什么或者为什么不?
对于那些认为自定义属性是一件好事的人:使用它们时要记住哪些事项?
对于那些认为自定义属性是坏事的人:你使用什么替代方案来完成类似的事情?
更新:我最感兴趣的是各种方法背后的推理,以及为什么一种方法比另一种方法更好。我认为我们都可以想出 4-5 种不同的方法来完成同一件事。(隐藏元素、内联脚本、额外类、从 ID 解析信息等)。
更新2:似乎 HTML 5 属性功能在这里得到了很多支持(我倾向于同意,它看起来是一个不错的选择)。到目前为止,我还没有看到太多对这个建议的反驳。使用这种方法是否有任何问题/陷阱需要担心?或者它只是对当前 W3C 规范的“无害”无效?data-
答:
避免使用自定义属性的最简单方法是使用现有属性。
使用有意义、相关的类名。
例如,执行如下操作: 和 ,
表示书籍和 CD。类更适合表示某物是什么。type='book'
type='cd'
例如class='book'
我过去使用过自定义属性,但老实说,如果您以语义上有意义的方式使用现有属性,则真的没有必要使用它们。
举一个更具体的例子,假设你有一个网站,提供不同类型商店的链接。您可以使用以下方法:
<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 商店,另一个是书店。
评论
以我的拙见,不应使用自定义属性,因为它们不进行验证。除此之外,您可以为单个元素定义许多类,例如:
<div class='class1 class2 class3'>
Lorem ipsum
</div>
评论
class
所有好的插件都支持元数据插件(允许每个标签选项)。
它还允许无限复杂的数据/数据结构,以及键值对。
<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”及其在层次结构中的位置来保持关系。我经常将这种方法与jQuery一起使用,而没有实际使用类似Ajax的技术。
评论
否。请尝试以下操作:
<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>
评论
我没有使用自定义属性,因为我正在输出 XHTML,因为我希望数据可以被第三方软件机器读取(尽管,如果我想的话,我可以扩展 XHTML 模式)。
作为自定义属性的替代方案,大多数情况下,我发现 id 和 class 属性(例如,如其他答案中提到的)就足够了。
另外,请考虑以下事项:
如果额外的数据是人类可读的,也是机器可读的,那么它需要使用(可见的)HTML 标签和文本进行编码,而不是作为自定义属性。
如果它不需要人类可读,那么也许可以使用不可见的 HTML 标签和文本对其进行编码。
有些人例外:他们允许自定义属性,在运行时由客户端的 Javascript 添加到 DOM 中。他们认为这没问题:因为自定义属性只在运行时添加到 DOM,所以 HTML 不包含自定义属性。
HTML 5 明确允许以 开头的自定义属性。因此,例如,是有效的。由于它得到了标准的官方支持,我认为这是自定义属性的最佳选择。而且它不需要你用 hacks 重载其他属性,所以你的 HTML 可以保持语义。data
<p data-date-changed="Jan 24 5:23 p.m.">Hello</p>
资料来源:http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes
评论
规范:创建一个 ASP.NET TextBox 控件,该控件使用 JavaScript 根据属性“DecimalSeparator”和“ThousandsSeparator”动态地将其文本格式化为数字。
将这些属性从控件传输到 JavaScript 的一种方法是让控件呈现出自定义属性:
<input type="text" id="" decimalseparator="." thousandsseparator="," />
自定义属性可通过 JavaScript 轻松访问。虽然使用具有自定义属性的元素的页面不会进行验证,但该页面的呈现不会受到影响。
只有当我想将字符串和整数等简单类型关联到 HTML 元素以用于 JavaScript 时,我才使用这种方法。如果我想使 HTML 元素更易于识别,我将使用 class 和 id 属性。
这是我最近一直在使用的一种技术:
<div id="someelement">
<!-- {
someRandomData: {a:1,b:2},
someString: "Foo"
} -->
<div>... other regular content...</div>
</div>
comment-object 与父元素(即 #someelement)相关联。
解析器如下:http://pastie.org/511358
要获取任何特定元素的数据,只需调用 parseData
,并引用作为唯一参数传递的该元素:
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 表示法)
- 不显眼,语义上比大多数替代品更干净
下面是解析器代码(从上面的 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;
};
})();
评论
对于复杂的 Web 应用程序,我会将自定义属性放到各处。
对于更多面向公众的页面,我使用“rel”属性并将所有数据转储到JSON中,然后使用MooTools或jQuery对其进行解码:
<a rel="{color:red, awesome:true, food: tacos}">blah</a>
我最近试图坚持使用 HTML 5 数据属性只是为了“准备”,但它还没有自然而然地出现。
评论
我们制作了一个基于 Web 的编辑器,它能够理解 HTML 的一个子集——一个非常严格的子集(邮件客户端几乎可以普遍理解)。我们需要在数据库中表达一些东西,但我们不能在 DOM 中表达它,否则编辑器运行的浏览器会吓坏(或者更有可能吓坏了,而不是可能因为自定义属性而吓坏了)。我们想要拖放,所以把它纯粹放在 DOM 中是不可行的,就像 jquery 一样(额外的数据没有被正确复制)。我们可能还需要额外的数据来配合骑行。最后,我们决定在编辑过程中使用,然后当我们发布所有内容时,我们删除并执行正则表达式搜索和销毁。<td width="@INSWIDTH_42@">
.data()
.html()
<td width="1234" rs-width="@INSWIDTH_42@">
width
s/rs-width=/width=/g
起初,写大部分内容的人是在这个问题上的验证纳粹,并尽一切努力避免我们的自定义属性,但最终默许了,因为似乎没有其他东西可以满足我们的所有要求。当他意识到自定义属性永远不会出现在电子邮件中时,这很有帮助,我们确实考虑过将额外的数据编码到 ,但决定这将是两害相权取其轻。class
就我个人而言,我更喜欢干净和通过验证器等,但作为公司员工,我必须记住,我的主要职责是推进公司的事业(尽快赚尽可能多的钱),而不是我对技术纯洁的自负渴望。工具应该为我们工作;不是我们为他们服务。
评论
如果为页面指定架构,则可以创建任何属性。
例如:
<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"/>
评论
addthis
xmlns
CustomElementRegistry.define()
我一直使用自定义字段,例如<a i=“” ....然后用 jquery 引用 i。无效的 html ,是的。它工作得很好,是的。
评论
我知道人们反对它,但我为此想出了一个超短的解决方案。如果您想使用像“mine”这样的自定义属性,例如:
<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;
});
与说自定义属性不会验证的答案相反:
自定义属性将进行验证。
自定义标签也是如此,只要自定义标签是小写和连字符的。
在任何验证器中尝试此操作。它将验证。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Custom Test</title>
</head>
<body>
<dog-cat PIANO="yellow">test</dog-cat>
</body>
</html>
一些验证者:
https://appdevtools.com/html-validator
https://www.freeformatter.com/html-validator.html
问题是:安全吗?以后会坏吗?
自定义标签
不存在带连字符的标记。我相信 W3C 永远不会使用带连字符的标签。如果他们这样做了,只要你使用一个不常见的前缀,你就永远不会看到冲突。例如。<johny-mytag>
自定义属性
有带连字符的 HTML 属性。但是 HTML 规范承诺永远不会使用以 开头的属性。所以保证安全。但是,我相信 W3C 永远不会引入任何以 .只要您的前缀不寻常,您就永远不会看到冲突。data-
data-myattrib
johny-
评论