Пользовательские атрибуты - да или нет?


в последнее время я все больше и больше читаю о людях, использующих пользовательские атрибуты в своих HTML-тегах, в основном с целью встраивания некоторых дополнительных битов данных для использования в коде javascript.

Я надеялся собрать некоторую обратную связь о том, является ли использование пользовательских атрибутов хорошей практикой, а также какие есть альтернативы.

Кажется, что это действительно может упростить и код на стороне сервера и клиента, но он также не совместим с W3C.

должны ли мы использовать пользовательские атрибуты HTML в наших веб-приложениях? Почему или почему нет?

для тех, кто считает, что пользовательские атрибуты являются хорошей вещью: что некоторые вещи, чтобы иметь в виду при их использовании?

для тех, кто думает, что пользовательские атрибуты-это плохо: какие альтернативы вы используете для достижения чего-то подобного?

обновление: меня больше всего интересует мышление за различные методы, а также как указывает на то, почему один метод лучше, чем другой. Я думаю, мы все можем придумать 4-5 разных способов сделать то же самое. (скрытые элементы, встроенные скрипты, дополнительные классы, анализ информации из идентификаторов и т. д.).

обновление 2: кажется, что HTML 5 data- атрибут функция имеет много поддержки здесь (и я склонен согласиться, это выглядит как твердый вариант). До сих пор я не видел много опровержений для этого предложения. Есть ли какие-либо проблемы / подводные камни беспокоиться об использовании этого подхода? Или это просто "безвредное" аннулирование текущих спецификаций W3C?

14 246

14 ответов:

HTML 5 явно разрешает пользовательские атрибуты, которые начинаются с data. Так, например, <p data-date-changed="Jan 24 5:23 p.m.">Hello</p> действителен. Поскольку он официально поддерживается стандартом, я думаю, что это лучший вариант для пользовательских атрибутов. И это не требует от вас перегружать другие атрибуты с помощью хаков, поэтому ваш 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).

вот парсер: 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/>), так как комментарии должны быть внутри элемент, который будет рассматриваться как данные этого элемента.


EDIT:

заметные преимущества этой техники:

  • легко реализовать
  • тут не недействительным 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;

    };

})();

вы можете создать любой атрибут, если вы укажете схему для вашей страницы.

например:

Addthis

<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', для представления книг и компакт-дисков. Классы гораздо лучше для представления чего-то и.

например 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 { }

В приведенном выше примере мы видим, что обе ссылки на магазины (в отличие от других ссылок на сайте) и один диск в магазине, а другой-книжный магазин.

встроить данные в 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!');

Я не вижу проблем в использовании существующих функций 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>

он сохраняет связь через четко определенный идентификатор / расширение "_extended" по вашему выбору и по его положению в иерархии. Я часто использую этот подход вместе с jQuery и без фактического использования Ajax, как методы.

Я не использую пользовательские атрибуты, потому что я опережаю XHTML, потому что я хочу, чтобы данные были машиночитаемыми сторонним программным обеспечением (хотя я мог бы расширить схему XHTML, если бы захотел).

в качестве альтернативы пользовательским атрибутам, в основном я нахожу атрибуты id и class (например, как упоминалось в других ответах) достаточными.

кроме того, рассмотрите это:

  • Если дополнительные данные должны быть читаемыми, а также машиночитаемый, затем он должен быть закодирован с использованием (видимых) HTML-тегов и текста вместо пользовательских атрибутов.

  • Если он не должен быть читаемым человеком, то, возможно, его можно закодировать с помощью невидимка HTML-теги и текст.

некоторые люди делают исключение: они разрешают пользовательские атрибуты, добавленные в DOM Javascript на стороне клиента во время выполнения. Они считают, что это нормально: потому что пользовательские атрибуты только добавленный в 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>

мы создали веб-редактор, который понимает подмножество HTML-очень строгое подмножество (которое понимается почти повсеместно почтовыми клиентами). Нам нужно выразить такие вещи, как <td width="@INSWIDTH_42@"> в базе данных, но мы не можем иметь это в DOM, в противном случае браузер, в котором работает редактор, выходит из себя (или, скорее всего, выйдет из себя, чем из-за пользовательских атрибутов). Мы хотели перетащить и падение, так что положить его чисто в DOM было вне, как и jquery .data() (дополнительные сведения не правильно скопировал). Мы, вероятно, также нуждались в дополнительных данных, чтобы прийти вместе для поездки в .html(). В конце концов мы остановились на использовании <td width="1234" rs-width="@INSWIDTH_42@"> во время процесса редактирования, а затем, когда мы публикуем все это, мы удаляем width и сделать регулярное выражение search-and-destroy s/rs-width=/width=/g.

сначала парень, пишущий большую часть этого, был валидатором-нацистом по этому вопросу и пытался все избежать нашего пользовательского атрибута, но в конце концов согласился, когда ничто другое, казалось, не работало для всех наших требования. Это помогло, когда он понял, что пользовательский атрибут никогда не появится в почта мы рассматривали возможность кодирования наших дополнительных данных в class, но решил, что будет большее из двух зол.

Лично Мне предпочитаю чтобы все было чисто и передает валидаторы и т. д. но как сотрудник компании я должен помнить, что моя основная ответственность заключается в продвижении дела компании (как можно больше денег как можно быстрее), а не в том, что мой эгоистическое стремление к технической чистоте. Инструменты должны работать на нас, а не мы на них.

Я знаю, что люди против этого, но я придумал супер короткое решение для этого. Если вы хотите использовать пользовательский атрибут, например "мой", например:

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

затем вы можете запустить этот код, чтобы получить объект, так как jQuery.данных() делает.

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

Spec:создать ASP.NET элемент управления TextBox, который динамически автоматически форматирует свой текст в виде числа, согласно свойствам "DecimalSeparator" и "ThousandsSeparator", используя JavaScript.


Одним из способов передачи этих свойств из элемента управления в JavaScript является то, чтобы элемент управления отображал пользовательские свойства:

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

пользовательские свойства легко доступны с помощью JavaScript. И в то время как страница, использующая элементы с пользовательскими свойствами, не будет проверка, рендеринг этой страницы не будет затронут.


Я только используйте этот подход, когда я хочу связать простые типы, такие как строки и целые числа, с элементами HTML для использования с JavaScript. Если я хочу сделать HTML-элементы легче идентифицировать, я буду использовать класс и id свойства.

Я использую пользовательские поля все время, например

для сложных веб-приложений я отбрасываю пользовательские атрибуты повсюду.

для более открытых страниц я использую атрибут " rel " и сбрасываю все свои данные там в JSON, а затем декодирую его с помощью MooTools или jQuery:

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

Я пытаюсь придерживаться атрибута данных HTML 5 в последнее время только для "подготовки", но он еще не пришел естественным образом.

настраиваемые атрибуты, по моему скромному мнению, не должны использоваться, поскольку они не проверяют. Альтернативой этому, вы можете определить много классов для одного элемента, как:

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