Пользовательские атрибуты - да или нет?
в последнее время я все больше и больше читаю о людях, использующих пользовательские атрибуты в своих HTML-тегах, в основном с целью встраивания некоторых дополнительных битов данных для использования в коде javascript.
Я надеялся собрать некоторую обратную связь о том, является ли использование пользовательских атрибутов хорошей практикой, а также какие есть альтернативы.
Кажется, что это действительно может упростить и код на стороне сервера и клиента, но он также не совместим с W3C.
должны ли мы использовать пользовательские атрибуты HTML в наших веб-приложениях? Почему или почему нет?
для тех, кто считает, что пользовательские атрибуты являются хорошей вещью: что некоторые вещи, чтобы иметь в виду при их использовании?
для тех, кто думает, что пользовательские атрибуты-это плохо: какие альтернативы вы используете для достижения чего-то подобного?
обновление: меня больше всего интересует мышление за различные методы, а также как указывает на то, почему один метод лучше, чем другой. Я думаю, мы все можем придумать 4-5 разных способов сделать то же самое. (скрытые элементы, встроенные скрипты, дополнительные классы, анализ информации из идентификаторов и т. д.).
обновление 2: кажется, что HTML 5 data-
атрибут функция имеет много поддержки здесь (и я склонен согласиться, это выглядит как твердый вариант). До сих пор я не видел много опровержений для этого предложения. Есть ли какие-либо проблемы / подводные камни беспокоиться об использовании этого подхода? Или это просто "безвредное" аннулирование текущих спецификаций W3C?
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; }; })();
вы можете создать любой атрибут, если вы укажете схему для вашей страницы.
например:
<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-destroys/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 в последнее время только для "подготовки", но он еще не пришел естественным образом.