本気でやるなら innerHTML を活用すべき

本気でやるならonclick属性は避けてライブラリを活用すべき - VTuberになったプログラマーの魂の残滓

僕は逆に onclick 属性を多用してしまいます。
たぶん『本気』の度合いが違うんだと思います。


『デザイナーとの分業の点からみれば使用しないほうが好ましい』というのは、『既に存在する HTML に対してイベントを追加する』という状況に限っていえば agree です。ただ JavaScrip で HTML を生成するという状況になると話が違います。JavaScript による HTML の生成においては createElement よりも innerHTML を使った方が数倍速い(特にIE)という事情から、onclick 属性を使うことが多くなります。正確にいうと onclick だけに限った話ではなく、イベントハンドラを HTML の属性として書けるので重宝するということです。


よくあるのは JSON で受け取ったデータから JavaScript で HTML を生成する場合などで、innerHTML を利用した書き方だと以下のようになります。

var items = [
  { title:'hoge', link:'/xxx/hoge', date:'2008/05/19 10:30' },
  { title:'fuga', link:'/yyy/fuga', date:'2008/05/19 14:00' }
];

function item_builder() {
  var html = [];
  for (var i = 0, len = items.length; i < len; i++)
      html.push('<li onclick="SomeFunc(', i, ')">', items[i].title, '</li>');

  $('container').innerHTML = html.join('');
}

イベントハンドラには index を渡して必要なデータは元データから参照することですっきり書けます。addEventLisner なしでも大抵の処理はこの書き方で書くことができます。


今の時代に JavaScript OFF な人を考慮していたらキリがないのですが、やるとすれば簡単に以下で足りると思います。JavaScript ON の人のみ上記のコードで内容が上書きされます。

<ul id="container">
  JavaScript を ON にして出直してきてください。 <br />
  どうしても嫌な人は <a href="hoge.html"> こちら </a>
</ul>


上の例では items の数が2つしかなかったけどこれが100個になったりもっと複雑な HTML になったりすると、明らかに体感速度で innerHTML の方が速くなります。prototype.js を用いた item_builder() の一般的な実装は以下のようになるでしょう。items の数を増やして速度を検証してみてください。

function item_builder2() {
  var container = $('container');
  items.each(function(e, i) {
    var element = new Element('li').update(items[i].title).observe('click', SomeFunc.bind(null, i));
    container.appendChild(element);
  }
}


「これライブラリ使ってるから不利じゃん!」という人は以下を使ってください。
以下をみてわかる通り、DOM Method を用いた HTML の組み立てはクロスブラウザを考えるとライブラリを使わないとやってられません。また、これだけやっても cloneNode などを駆使することで prototype.js を用いた例の方が速い可能性すらあります。

function item_builder3() {
  var container = document.getElementById('container');
  if (window.attachEvent) {  // if IE
    for (var i = 0, len = items.length; i < len; i++) {
      var element = document.createElement('li');
      element.innerText = items[i].title;
      element.attachEvent('onclick', (function(index){ return function(){SomeFunc(index)} })(i));
      container.appendChild(element);
    }
  } else {
    for (var i = 0, len = items.length; i < len; i++) {
      var element = document.createElement('li');
      element.textContent = items[i].title;
      element.addEventListener('click', (function(index){ return function(){SomeFunc(index)} })(i), false);
      container.appendChild(element);
    }
  }
}

innerHTML ってスゴい :-)

  • ライブラリ依存もなくクロスブラウザも完璧で、
  • コードも短く、
  • それでいて速い、

ただこれは『カレンダーを作る』とか『Gmailを作る』とかいったような、大量の HTML を生成&操作したい場合の話であって、通常(なにをもって通常というのかはわかりませんが)は DOM で操作した方が楽な場合が多いです。


なんか innerHTML vs DOM Method の話ばかりですが、これが僕が onclick を使用する理由です。
要は時と場合によりけりで、『古いので使うな』というのは違う気がします。