最近、HTMLタグでカスタム属性を使用する人々について、主にjavascriptコードで使用するためのデータの一部を埋め込む目的で、ますます多くの記事を読んでいます。
カスタム属性を使用するのが良い方法であるかどうか、またいくつかの代替手段が何であるかについてフィードバックを集めたいと思っていました。
サーバー側とクライアント側のコードbothの両方を本当に単純化できるようですが、W3C準拠ではありません。
WebアプリでカスタムHTML属性を使用する必要がありますか?なぜですか?
カスタム属性は良いことだと思う人のために:それらを使用するときに留意すべきことは何ですか?
カスタム属性は悪いことだと思う人のために:似たようなことを達成するためにどのような選択肢を使用しますか?
更新:私は主に、さまざまな方法の背後にある推論と、1つの方法がなぜであるかのポイントに興味があります別よりも優れています。同じことを達成するために、4〜5つの異なる方法を考え出すことができると思います。 (隠し要素、インラインスクリプト、追加のクラス、IDからの情報の解析など)。
更新2: HTML 5 data-
属性機能はここで多くのサポートを持っているようです(そして、私は同意する傾向があります、それは堅実なオプションのように見えます)。これまでのところ、この提案に対する反論についてはあまり見ていません。このアプローチの使用について心配する問題/落とし穴はありますか?それとも、単に現在のW3C仕様の「無害な」無効化ですか?
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
これを使用する唯一の欠点は、コメントがwithin要素のデータと見なされる要素でなければならないため、自己閉鎖要素(たとえば、<img/>
)と共に使用できないことです。
編集:
この手法の顕著な利点:
これがパーサーコードです(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'
のようなことをして、本と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ストアで、もう一方は本屋です。
Domにデータを埋め込み、 jQuery に metadata を使用します。
優れたプラグインはすべて、メタデータプラグインをサポートしています(タグごとのオプションを許可)。
また、キーと値のペアだけでなく、無限に複雑なデータ/データ構造も使用できます。
<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!');
既存の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/extension "_extended"を介して、また階層内の位置によってリレーションを保持します。私はよく、この手法をjQueryと一緒に使用し、実際にAjaxのような手法を使用しません。
XHTMLを出力しているため、カスタム属性を使用していません。これは、サードパーティのソフトウェアでデータを機械可読にするためです(ただし、必要に応じてXHTMLスキーマを拡張できます)。
カスタム属性の代替として、ほとんどの場合、id属性とclass属性(他の回答で言及されているように)で十分です。
また、これを考慮してください:
余分なデータを人間が読み取れるだけでなく機械が読み取れるようにする場合は、カスタム属性としてではなく、(可視の)HTMLタグとテキストを使用してエンコードする必要があります。
人間が読めるものである必要がない場合は、おそらくinvisible HTMLタグとテキストを使用してエンコードできます。
一部の人々は例外を作ります:彼らはカスタム属性を許可し、実行時にクライアント側でJavascriptによってDOMに追加されます。カスタム属性は実行時にのみDOMに追加されるため、HTMLにはカスタム属性は含まれません。
HTMLのサブセットを理解するWebベースのエディターを作成しました-非常に厳密なサブセット(メールクライアントによってほぼ普遍的に理解される)。データベースで<td width="@INSWIDTH_42@">
のようなものを表現する必要がありますが、それをDOMに含めることはできません。そうしないと、エディターが実行されているブラウザーがフリークします(または、フリークする可能性よりもフリークする可能性が高いカスタム属性を超えて)。ドラッグアンドドロップが必要だったため、jqueryの.data()
(余分なデータは適切にコピーされませんでした)と同様に、純粋にDOMに配置しました。おそらく、.html()
に乗るために追加のデータが必要になりました。最後に、編集プロセス中に<td width="1234" rs-width="@INSWIDTH_42@">
を使用することに決め、それからPOSTをすべて削除したら、width
を削除し、正規表現の検索と破棄s/rs-width=/width=/g
。
最初はこの問題のほとんどを書いている人がこの問題の検証ナチであり、カスタム属性を回避するためにすべてを試しましたが、最終的にはすべての要件にうまくいかないように思われたときに黙認しました。カスタム属性がemailに表示されないことに気付いたときに役立ちました。追加データをclass
にエンコードすることを検討しましたが、それは2つの悪の大きい方であると判断しました。
個人的に、私はprefer物事をきれいにし、バリデーターなどを渡すために、会社の従業員として、私の主な責任は会社の原因を推進すること(できるだけ早くお金を稼ぐこと)であることを覚えておく必要があります、技術的な純粋さに対する私の自己欲の欲求ではありません。ツールが機能するはずです。彼らのためではありません。
私は人々がそれに反対していることを知っていますが、私はこれに対して非常に短い解決策を思いつきました。たとえば、「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;
});
いや。代わりに次のようなものを試してください。
<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>
たとえば、<a i = "" ...のように常にカスタムフィールドを使用します。その後、jqueryでiを参照します。無効なhtml、はい。はい、うまくいきます。
仕様:JavaScriptを使用して、プロパティ "DecimalSeparator"および "ThousandsSeparator"に従って、テキストを数値として動的に自動フォーマットするASP.NET TextBoxコントロールを作成します。
これらのプロパティをコントロールからJavaScriptに転送する1つの方法は、コントロールにカスタムプロパティをレンダリングさせることです。
<input type="text" id="" decimalseparator="." thousandsseparator="," />
カスタムプロパティはJavaScriptで簡単にアクセスできます。また、カスタムプロパティを持つ要素を使用するページは validate ではありませんが、そのページのレンダリングは影響を受けません。
I only JavaScriptで使用するHTML要素に文字列や整数などの単純な型を関連付けたい場合、このアプローチを使用します。 HTML要素を識別しやすくしたい場合は、classおよびidプロパティを使用します。
複雑なWebアプリの場合、カスタム属性をあらゆる場所にドロップします。
より一般向けのページでは、「rel」属性を使用し、そこにあるすべてのデータをJSONでダンプしてから、MooToolsまたはjQueryでデコードします。
<a rel="{color:red, awesome:true, food: tacos}">blah</a>
私は最近「準備」のためだけにHTML 5データ属性に固執しようとしていますが、それはまだ自然に来ていません。