querySelectorAllという存在を知り、さっそくToDoアプリでgetElementsByTagNameを使っているところを書き換えようとしたとき、問題が発生した。
それは、以下の違いによるものだった。
- getElementsByTagName : 動的なNodeList
- querySelectorAll : 静的なNodeList
追記:2015/04/25 16:40
コメントで指摘していただいた箇所について追記する。ご指摘ありがとうございました!
※ コメント通知で気づいた時にはすでに削除?されていたっぽいですが
getElementByTagName について
- 日本語MDN・DOM3 :
NodeList
が返ってくる - US版MDN・DOM4 :
HTMLCollection
が返ってくる
ゆくゆくは、NodeListではなくHTMLCollection が返ってくるようになる。
どちらもcollectionに変わりないが、メソッドが少し違うので注意。
具体例をあげて違いをまとめていく。
ついでにquerySelectorAllの代替案として、ID指定のgetElementsByTagNameについても載せておく。
HTML
以降、このHTMLをもとにして進めていく。
getElementsByTagName
getElementsByTagNameは、指定したタグ名を持つリスト(NodeList)を取得するメソッド。
しかし、このままではHTMLにある全てのタグ要素を取得してしまう。
それを解決するために、querySelectorAllを使用する。
querySelectorAll
querySelectorAllは、CSSセレクタにマッチする要素のリスト(NodeList)を取得するメソッド。
jQueryで「$(‘#id > li’)」みたいに書く感覚だ。
うまい具合にID指定をしつつ、LI要素を取得することができる。
しかし、前述の通り、querySelectorAllは「静的なNodeList」のため、取得した時点でのNodeListを保持してしまう。
そのため、サンプルにあるように、要素を追加してもlengthが1のままになってしまう。
IDを指定したい。でも動的なNodeListが欲しいという場合の対応法について、次で説明する。
ID指定のgetElementsByTagName
IDを指定しつつ、動的なNodeListを取得したい場合は、以下のようにすればよい。
ちょっと長くなってしまうが、getElementByIdとgetElementsByTagNameを併用すればよい。
他にもgetElementsByClassNameなどとも併用できる。
以上
written by @bc_rikko
HTMLのcollectionでハマりやすいところを捉えたいい記事だと思います。
返信削除ただ、一つ気になるのは、動的なNodeListと静的なNodeListとされている点です。
確かに、NodeListには静的なものと動的なものが有ります。
->https://developer.mozilla.org/ja/docs/Web/API/NodeList
childNodesなどが動的なもの、querySelectorAllなどが静的なものとされています。
ただ、getElementsByTagNameで取得したものは、NodeListではなく、HTMLCollectionです。
MDNの日本語版やDOM3ではNodeListが返ってくることになっていますが、
MDNのUS版や、DOM4では、HTMLCollectionが返ることになっています。
->http://www.w3.org/TR/domcore/
FirefoxやChrome等のブラウザの実装もそれに追従しています。
NodeListもHTMLCollectionもcollectionには変わりないのですが、メソッドが少し違うという点があります。
どちらもArray.from等で配列化してしまえば意味ないんですけどね。参考までに。
ご指摘ありがとうございます!
削除内容は、本文に追記いたしました。
ちょっとした手違いでコメントを非公開にしてしまい、今まで削除されたものだと勘違いしておりました。
申し訳ございません。