30分くらいはまった。
条件
- 要素にdata属性がある。
- data属性はある要素のアクションによって動的に変化する。
HTML
<div class="change-data" data-category="me">me</div>
<div class="change-data" data-category="my">my</div>
<div class="change-data" data-category="mine">mine</div>
<div class="get-data" data-category="i">データあるよ</div>
JavaScript
$('.change-data').on('click', function(){
$('.get-data').attr('data-category', $(this).data("category"));
});
$(document).on('click', '.get-data', function(){
console.log($(this).data('category'));
});
求める挙動
- ロード時、.get-dataをクリックすると「i」が取得できる。
- .change-dataをクリックすると、.get-dataのdata-categoryが変化する。
- 再度.get-dataをクリックすると、.change-dataから取得したdata-categoryが取得できる。
実際の挙動
- ロード時、.get-dataをクリックすると「i」が取得できる。
- .change-dataをクリックすると、.get-dataのdata-categoryが変化する。
- 再度.get-dataをクリックすると、問答無用で「i」(初期値) が返ってくる。
なんで?
原因は以下の通り。
- jQueryが (?) data属性をキャッシュしている。
- attr()メソッドで書き換えているのはHTML上の属性値だけで、jQueryオブジェクト上では上書きできていない。
えー。
ちなみに、.change-dataクリック時の処理を下記に変えてみると?
JavaScript
$('.change-data').on('click', function(){
$('.get-data').data('category', $(this).data("category"));
});
- jQueryオブジェクト上は上書きできるが、HTML上の属性値は変化しない。
(゚Д゚) ハァ?
暫定的な解決策
data()メソッドは絶対に使わない前提で、全部attrにしちゃおうぜ!
JavaScript
$('.change-data').on('click', function(){
$('.get-data').attr('data-category', $(this).attr("data-category"));
});
$(document).on('click', '.get-data', function(){
console.log($(this).attr('data-category'));
});
真 (?) の解決策
ネイティブJSのdataset使おうぜ!
JavaScript
$('.change-data').on('click', function(){
$('.get-data')[0].dataset.category = $(this).data("category");
});
なお、datasetのサポート状況は下記の通り。
ブラウザー | バージョン |
---|---|
IE | 11~ |
Firefox | 6~ |
Chrome | 7~ |
Safari | 5.1~ |
Opera | 11.5~ |
iOS | 5.0~ |
Android | 3~ |
古いIEやAndroidブラウザーでは、getAttributeかattr()メソッドを使えって事ですかね。
なんだこの中途半端なメソッドは……。