はじめに
初めまして。
以前ははてなブログ(http://kde.hateblo.jp/)の方に技術ネタを書いていたのですが、こちらの方がフィードバック等もらえて勉強になるのではと思い、今回初めて投稿させて頂きます。
読みにくいところ等あるかと思いますが、お気づきの点等あればお気軽にご指摘いただけると幸いです。
今回の元ネタ
2か月ほど前に私自身がteratailに質問した「ネイティブのJSでデリゲートイベントを実装して子要素の情報を取得したいです」で返答頂いた、closest()メソッドについてです。
(当時ご回答頂いた方々、改めてありがとうございました)
closest()とは
Element.closest()メソッドは、パラメータで指定されたセレクタに一致する、現在の要素(または現在の要素自体)の最も近い祖先を返します。そのような祖先がない場合、nullを返します。
(Element.closest() - Web API インターフェイス | MDNより)
構文
const elem = element.closest(selector);
- 引数には'a:hover'や':not(div)'など、document.querySelector(selector)と同じようにセレクタを指定できます。
- セレクタが有効な文字列ではない場合はシンタックスエラーとなります。
- 戻り値は、elementの最も近い祖先要素です。マッチしない場合は
null
が返ります。
対応ブラウザ
IEには対応していません。
IEに対応するためにはMDNで紹介されているポリフィルを使用すると良いと思います。
(IE9以上、IE8以上の2つ用意されています)
実際の使用例
先述のtetatailの内容を実装してみたいと思います(一部HTMLは簡略化してあります)。
<div id="container">
<ul>
<li id="item1"><a href="#1">item</a></li>
<li id="item2"><a href="#2">item</a></li>
<li id="item3"><a href="#3">item</a></li>
<li id="item4"><a href="#4">item</a></li>
<li id="item5"><a href="#5">item</a></li>
</ul>
<button>add</button>
</div>
'use strict';
const container = document.getElementById('container');
const list = container.getElementsByTagName('ul')[0];
const items = list.children;
let itemCount = items.length;
const btn = container.getElementsByTagName('button')[0];
/**
* 値の取得
*/
const getValue = () => {
const result = {
id: '',
href: ''
}
list.addEventListener('click', (e) => {
const target = e.target;
if (target.nodeName !== 'A') { return; }
const li = target.closest('li');
result.id = li.id;
result.href = target.getAttribute('href');
console.log(result);
});
}
/**
* list要素の追加
*/
const addItem = () => {
btn.addEventListener('click', () => {
const li = document.createElement('li');
itemCount += 1;
li.id = `item${itemCount}`;
li.innerHTML = `<a href="#${itemCount}">item</item></li>`;
list.appendChild(li);
});
}
getValue();
addItem();
使ってみての感想
祖先要素を参照する方法としてはwhileでparentNodeを辿っていく方法が定番なのかと思いますが、closest()を使えばより簡潔でわかりやすく書けることが実感できました。
対応ブラウザに気を付けながら積極的に使っていきたいメソッドです。