自定义属性 - 是还是不是?

IT技术 javascript html xhtml custom-attribute
2021-02-01 17:46:14

最近我阅读了越来越多的关于人们在 HTML 标签中使用自定义属性的文章,主要是为了嵌入一些额外的数据以在 javascript 代码中使用。

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

现在看来似乎真的可以简化服务器端和客户端的代码,但它也不是W3C标准。

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

对于那些认为自定义属性是一件好事的人来说:使用它们时要记住哪些事情?

对于那些认为自定义属性不好的人:您使用哪些替代方法来完成类似的事情?

更新: 我最感兴趣的是各种方法背后推理,以及为什么一种方法比另一种方法更好的观点。我认为我们都可以想出 4-5 种不同的方法来完成同一件事。(隐藏元素、内联脚本、额外类、从 id 解析信息等)。

更新 2: 似乎 HTML 5data-属性特性在这里有很多支持(我倾向于同意,它看起来像一个可靠的选择)。到目前为止,我还没有看到对这个建议的反驳。使用这种方法是否有任何问题/陷阱需要担心?或者它只是对当前 W3C 规范的“无害”失效?

6个回答

HTML 5 明确允许以data. 因此,例如,<p data-date-changed="Jan 24 5:23 p.m.">Hello</p>是有效的。由于它受到标准的正式支持,我认为这是自定义属性的最佳选择。并且它不需要您使用 hack 重载其他属性,因此您的 HTML 可以保持语义。

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

这是一个很好的方法.. 但我怀疑它是否适用于您必须支持 IE 6 和其他旧浏览器。
2021-03-21 17:46:14
@Wahnfrieden:w3.org/TR/REC-html40/intro/sgmltut.html#idx-attribute-8,这是经批准的、符合标准的方法。这在此处得到了很好的描述和演示:rodsdot.com/html/... 正如之前其他人发布的那样。
2021-03-22 17:46:14
它适用于在 HTMLElement 上使用 getAttribute() 方法的所有浏览器。另外,随着 HTML5 数据集支持的增长,您可以轻松地添加它。
2021-03-28 17:46:14
我很确定它确实适用于较旧的浏览器;这些属性被添加到 DOM 中,您可以在其中访问它们。
2021-04-03 17:46:14
@Chuck 显然您可以向 DOCTYPE 添加属性:rodsdot.com/html/... - 不是我认为这是一个好主意,但它似乎是标准化的。
2021-04-03 17:46:14

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

<div id="someelement">

    <!-- {
        someRandomData: {a:1,b:2},
        someString: "Foo"
    } -->

    <div>... other regular content...</div>
</div>

评论对象与父元素(即#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;

    };

})();
有人应该把它做成一个 jquery 插件
2021-03-11 17:46:14
让我强调@MGOwen 的声明:不要使用注释来添加功能。特别是在 HTML 中。你不使用压缩器吗?您将无法在不破坏代码的情况下删除注释。这也意味着您不能再添加真正的评论。
2021-03-21 17:46:14
出于好奇,您使用什么方法进行自闭合标签?我通常需要在 <input> 元素上使用这样的东西(以帮助客户端验证规则)。在这种情况下你有什么选择?
2021-03-22 17:46:14
评论应该能够在不破坏任何内容的情况下更改/删除。这就是重点。因此,将任何对标记或代码重要的内容放入注释中是一个坏主意。未来的开发人员很容易认为它们是评论并删除它们。对于这个问题,我们已经有了一个真正的解决方案:以“data-”为前缀的自定义属性。永远不应该使用这种方法。
2021-03-24 17:46:14
我可能会使用类似的技术,而不是将评论数据绑定到“parentNode”,它可以绑定到评论的“previousSibling”......然后你可以在 <input/> 之后立即添加评论,它会工作:<input/><!--{data:123}-->
2021-03-27 17:46:14

如果为页面指定架构,则可以创建任何属性。

例如:

添加这个

<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。类更适合表示某物什么

例如 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,我将它的类设置为“layout-xxx”,或者对于围绕重要部分(如书籍或商店)的内部 div,我将使用 content-book 或 content-store . 然后在我的 JavaScript 中,我有一个函数可以根据我要查找的内容在标签上添加这些内容。它对我来说有助于保持干净和有条理,但需要一定程度的纪律和预先组织。
2021-04-01 17:46:14
遗憾的是,同时为两个类编写 css 选择器(.ab 注意缺少的空格)在 IE 中不起作用。不过它确实适用于 Firefox 和其他浏览器。仍然,使用类是将附加语义嵌入标记的好方法
2021-04-02 17:46:14
好点,但公平地说,“类型”仅对某些标签有效,并且当它是有效属性时,它还具有有效值列表,因此您仍然不真正符合 w3c。
2021-04-04 17:46:14
@Jonathan 双班制效果很好,除非在“值”未知的情况下。例如,如果它是某种整数 id,我们不能很好地选择每种可能的情况。然后我们需要手动解析 class 属性,这绝对可行,但在代码中不是很清楚,并且在某些情况下,可能会非常慢(如果有很多候选元素要解析)。
2021-04-06 17:46:14
我的观点是你不应该为此使用类型标签。因此如果你是......那么你应该......我会编辑以使其更清楚
2021-04-08 17:46:14

将数据嵌入 dom 并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!');
破坏class属性只是使用插件的方法之一这不是唯一的方法。
2021-03-25 17:46:14
您被否决的另一个原因是建议使用一个根本不需要插件的插件。
2021-03-27 17:46:14
当存在 W3C 批准的指定自定义属性的方式时损坏类属性可能是您被否决的原因。
2021-04-08 17:46:14