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

发布于 2024-07-24 05:27:40 字数 624 浏览 6 评论 0 原文

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

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

看起来它确实可以简化服务器端和客户端代码,但它也不符合 W3C。

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

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

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

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

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

Recently I have been reading more and more about people using custom attributes in their HTML tags, mainly for the purpose of embedding some extra bits of data for use in javascript code.

I was hoping to gather some feedback on whether or not using custom attributes is a good practice, and also what some alternatives are.

It seems like it can really simplify both server side and client side code, but it also isn't W3C compliant.

Should we be making use of custom HTML attributes in our web apps? Why or why not?

For those who think custom attributes are a good thing: what are some things to keep in mind when using them?

For those who think custom attributes are bad thing: what alternatives do you use to accomplish something similar?

Update: I'm mostly interested in the reasoning behind the various methods, as well as points as to why one method is better than another. I think we can all come up with 4-5 different ways to accomplish the same thing. (hidden elements, inline scripts, extra classes, parsing info from ids, etc).

Update 2: It seems that the HTML 5 data- attribute feature has a lot of support here (and I tend to agree, it looks like a solid option). So far I haven't seen much in the way of rebuttals for this suggestion. Are there any issues/pitfalls to worry about using this approach? Or is it simply a 'harmless' invalidation of the current W3C specs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

五里雾 2024-07-31 05:27:40

HTML 5 明确允许以 data 开头的自定义属性。 因此,例如,

Hello

是有效的。 由于它受到标准的正式支持,我认为这是自定义属性的最佳选择。 而且它不需要您通过 hack 来重载其他属性,因此您的 HTML 可以保持语义。

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

HTML 5 explicitly allows custom attributes that begin with data. So, for example, <p data-date-changed="Jan 24 5:23 p.m.">Hello</p> is valid. Since it's officially supported by a standard, I think this is the best option for custom attributes. And it doesn't require you to overload other attributes with hacks, so your HTML can stay semantic.

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

奈何桥上唱咆哮 2024-07-31 05:27:40

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

<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

使用它的唯一缺点是它不能与自闭合元素一起使用(例如 ),因为注释必须位于元素内才能被视为该元素的数据。


编辑

此技术的显着优点:

  • 易于实现
  • 不会使 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;

    };

})();

Here's a technique I've been using recently:

<div id="someelement">

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

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

The comment-object ties to the parent element (i.e. #someelement).

Here's the parser: http://pastie.org/511358

To get the data for any particular element simply call parseData with a reference to that element passed as the only argument:

var myElem = document.getElementById('someelement');

var data = parseData( myElem );

data.someRandomData.a; // <= Access the object staight away

It can be more succinct than that:

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

Access it:

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

The only disadvantage of using this is that it cannot be used with self-closing elements (e.g. <img/>), since the comments must be within the element to be considered as that element's data.


EDIT:

Notable benefits of this technique:

  • Easy to implement
  • Does not invalidate HTML/XHTML
  • Easy to use/understand (basic JSON notation)
  • Unobtrusive and semantically cleaner than most alternatives

Here's the parser code (copied from the http://pastie.org/511358 hyperlink above, in case it ever becomes unavailable on 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;

    };

})();
海螺姑娘 2024-07-31 05:27:40

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

例如:

添加此

<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"/>

You can create any attribute if you specify a schema for your page.

For example:

Addthis

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

Facebook (even tags)

<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"/>
谁的年少不轻狂 2024-07-31 05:27:40

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

使用有意义的、相关的类名。
例如,执行以下操作: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 商店,另一个是一本书店铺。

The easiest way to avoid use of custom attributes is to use existing attributes.

use meaningful, relevant class names.
For example, do something like: type='book' and type='cd',
to represent books and cds. Classes are much better for representing what something IS.

e.g. class='book'

I have used custom attributes in the past, but honestly, there really isn't a need to for them if you make use of existing attributes in a semantically meaningful way.

To give a more concrete example, let's say you have a site giving links to different kinds of stores. You could use the following:

<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 styling could use classes like:

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

In the above example we see that both are links to stores (as opposed to the other unrelated links on the site) and one is a cd store, and the other is a book store.

邮友 2024-07-31 05:27:40

将数据嵌入到dom中,并使用元数据作为jQuery

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

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

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

OR

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

OR

<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!');

Embed the data in the dom and use metadata for jQuery.

All the good plug-ins support the metadata plugin(allowing per tag options).

It also allows infinitely complex data/data structures, as well as key-value pairs.

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

OR

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

OR

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

Then get the data like so:

var data = $('li.someclass').metadata();
if ( data.some && data.some == 'random' )
alert('It Worked!');
昇り龍 2024-07-31 05:27:40

我认为使用现有的 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 的技术。

I see no problem in using existing XHTML features without breaking anything or extending your namespace. Let's take a look at a small example:

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

How to add additional information to some_content without additional attributes? What about adding another tag like the following?

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

It keeps the relation via a well defined id/extension "_extended" of your choice and by its position in the hierarchy. I often use this approach together with jQuery and without actually using Ajax like techniques.

青柠芒果 2024-07-31 05:27:40

不。 尝试这样的事情:

<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>

Nay. Try something like this instead:

<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>
风吹雪碎 2024-07-31 05:27:40

我没有使用自定义属性,因为我正在输出 XHTML,因为我希望数据可由第 3 方软件机器读取(尽管,如果我愿意,我可以扩展 XHTML 架构)。

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

另外,请考虑这一点:

  • 如果额外数据既可供人类读取又可供机器读取,则需要使用(可见)HTML 标记和文本而不是自定义属性对其进行编码。

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

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

I'm not doing using custom attributes, because I'm outputing XHTML, because I want the data to be machine-readable by 3rd-party software (although, I could extend the XHTML schema if I wanted to).

As an alternative to custom attributes, mostly I'm finding the id and class attributes (e.g. as mentioned in other answers) sufficient.

Also, consider this:

  • If the extra data is to be human-readable as well as machine-readable, then it needs to be encoded using (visible) HTML tags and text instead of as custom attributes.

  • If it doesn't need to be human readable, then perhaps it can be encoded using invisible HTML tags and text.

Some people make an exception: they allow custom attributes, added to the DOM by Javascript on the client side at run-time. They reckon this is OK: because the custom attributes are only added to the DOM at run-time, the HTML contains no custom attributes.

用心笑 2024-07-31 05:27:40

我们制作了一个基于 Web 的编辑器,它可以理解 HTML 的一个子集 - 一个非常严格的子集(几乎可以被邮件客户端普遍理解)。 我们需要在数据库中表达诸如 之类的内容,但我们不能在 DOM 中表达这样的内容,否则编辑器运行的浏览器会崩溃(或者比因自定义属性而惊慌失措的可能性更大)。 我们想要拖放,因此将其纯粹放入 DOM 中是不可行的,jquery 的 .data() 也是如此(额外的数据没有正确复制)。 我们可能还需要在 .html() 中提供额外的数据。 最后我们决定在编辑过程中使用 ,然后当我们发布所有内容时,我们删除 width 并执行正则表达式搜索并销毁s/rs-width=/width=/g

起初,写大部分内容的人是这个问题上的验证纳粹分子,并尝试了一切来避免我们的自定义属性,但最终默许了,因为没有其他方法似乎可以满足我们的所有要求。 当他意识到自定义属性永远不会出现在电子邮件中时,这很有帮助。我们确实考虑过在中编码我们的额外数据,但认为这将是两害相权取其大。

就我个人而言,我更喜欢让事情干净并通过验证器等,但作为公司员工,我必须记住,我的主要责任是推进公司的事业(尽快赚尽可能多的钱),这并不是我对技术纯粹性的自私渴望。 工具应该为我们所用; 不是我们为了他们。

We've made a web-based editor that understands a subset of HTML - a very strict subset (that understood nearly universally by mail clients). We need to express things like <td width="@INSWIDTH_42@"> in the database, but we can't have that in the DOM, otherwise the browser where the editor runs, freaks out (or is more likely to freak out than it is likely to freak out over custom attributes). We wanted drag-and-drop, so putting it purely in the DOM was out, as was jquery's .data() (the extra data didn't get copied properly). We probably also needed the extra data to come along for the ride in .html(). In the end we settled on using <td width="1234" rs-width="@INSWIDTH_42@"> during the editing process, and then when we POST it all, we remove width and do a regex search-and-destroy s/rs-width=/width=/g.

At first the guy writing most of this was the validation-nazi on this issue and tried everything to avoid our custom attribute, but in the end acquiesced when nothing else seemed to work for ALL our requirements. It helped when he realized that the custom attribute would never appear in an email We did consider encoding our extra data in class, but decided that would be the greater of two evils.

Personally, I prefer to have things clean and passing validators etc., but as a company employee I have to remember that my primary responsibility is advancing the company's cause (making as much money as quickly as possible), not that of my egotistical desire for technical purity. Tools should work for us; not us for them.

琉璃梦幻 2024-07-31 05:27:40

我知道人们反对它,但我为此想出了一个超短的解决方案。 如果您想使用像“我的”这样的自定义属性,

<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;
});

I know people are against it, but I came up with a super short solution for this. If you want to use a custom attribute like "mine" so for example:

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

Then you can run this code to get an object back just like jquery.data() does.

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;
});
眼眸里的那抹悲凉 2024-07-31 05:27:40

对于复杂的 Web 应用程序,我将自定义属性放在各处。

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

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

我最近尝试坚持使用 HTML 5 数据属性只是为了“准备”,但它还没有还没有自然到来。

For complex web apps, I drop custom attributes all over the place.

For more public facing pages I use the "rel" attribute and dump all my data there in JSON and then decode it with MooTools or jQuery:

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

I'm trying to stick with HTML 5 data attribute lately just to "prepare", but it hasn't come naturally yet.

抱着落日 2024-07-31 05:27:40

规范:使用 JavaScript 创建一个 ASP.NET TextBox 控件,根据属性“DecimalSeparator”和“ThousandsSeparator”动态地将其文本自动格式化为数字。

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

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

JavaScript 可以轻松访问自定义属性。 虽然使用具有自定义属性的元素的页面不会验证,但该页面的呈现不会做作的。

当我想要将字符串和整数等简单类型关联到 HTML 元素以与 JavaScript 一起使用时,我使用此方法。 如果我想让 HTML 元素更容易识别,我将使用 classid 属性。

Spec: Create an ASP.NET TextBox control which dynamically auto-formats its text as a number, according to properties "DecimalSeparator" and "ThousandsSeparator", using JavaScript.

One way to transfer these properties from the control to JavaScript is to have the control render out custom properties:

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

Custom properties are easily accessible by JavaScript. And whilst a page using elements with custom properties won't validate, the rendering of that page won't be affected.

I only use this approach when I want to associate simple types like strings and integers to HTML elements for use with JavaScript. If I want to make HTML elements easier to identify, I'll make use of the class and id properties.

十二 2024-07-31 05:27:40

我一直使用自定义字段,例如

I use custom fields all the time for example <a i="" .... Then reference to i with jquery. Invalid html , yes. It works well, yes.

爱她像谁 2024-07-31 05:27:40

与自定义属性不会验证的答案相反:

自定义属性验证。

自定义标签也将验证,只要自定义标签是小写并用连字符连接即可。

在任何验证器中尝试此操作。 它会验证。

<!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

https://validator.w3.org/nu/

问题是:安全吗? 以后会中断吗?

自定义标签

没有连字符标签存在。 我相信 W3C 永远不会使用连字符标记。 如果他们这样做了,只要您使用不常见的前缀,您就永远不会看到冲突。 例如

自定义属性

有连字符的 HTML 属性。 但 HTML 规范承诺永远不会使用以 data- 开头的属性。 所以 data-myattrib 保证是安全的。 不过,我相信W3C永远不会引入任何以johny-开头的属性。 只要您的前缀不寻常,您就永远不会看到冲突。

Contrary to answers which say custom attributes won't validate:

Custom attributes will validate.

So will custom tags, as long as the custom tags are lowercase and hyphenated.

Try this in any validator. It will validate.

<!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>

Some validators:

https://appdevtools.com/html-validator

https://www.freeformatter.com/html-validator.html

https://validator.w3.org/nu/

The question is: Is it safe? Will it break later?

Custom Tags

No hyphenated tags exist. I believe that W3C will never use a hyphenated tag. And if they did, as long as you use an uncommon prefix, you'll never see a conflict. Eg.<johny-mytag>.

Custom Attributes

There are hyphenated HTML attributes. But the HTML spec promises never to use an attribute starting with data-. So data-myattrib is guaranteed to be safe. However, i believe that W3C will never introduce any attribute that starts with johny-. As long as your prefix is unusual, you'll never see a conflict.

夜空下最亮的亮点 2024-07-31 05:27:40

以我的拙见,不应使用自定义属性,因为它们无法验证。 除此之外,您可以为单个元素定义许多类,例如:

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

Custom attributes, in my humble opinion, should not be used as they do not validate. Alternative to that, you can define many classes for a single element like:

<div class='class1 class2 class3'>
    Lorem ipsum
</div>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文