#目的
自分用
<div class="e1">
<div class="e1-1">
<div class="e1-1-1"></div>
<div class="e1-1-2">
<div class="e1-1-2-1">
</div>
<div class="e1-1-3"></div>
</div>
</div>
javascriptで上記のような要素の生成と追加を繰り返すコードをスッキリさせたかった。
下記のように書くと上記HTMLを出力するようにしたい。
const c = 'className';
const elmement =
childAppender(el('div',{[c]:'e1'}),
siblingAppender(el('div',{[c]:'e1-1'}),
el('div',{[c]:'e1-1-1'}),
childAppender(el('div',{[c]:'e1-1-2'}),
el('div',{[c]:'e1-1-2-1'})
),
el('div',{[c]:'e1-1-3'})
)
);
console.log(elmement); //上記HTMLのような構造を出力
第一引数は親要素となる為、慣れないと少しややこしい。
#関数
以下の関数を用いる
//要素の生成
const el = (tag, attr) => {
if (!tag) return null;
const elm = document.createElement(tag);
if (!attr) return elm;
const map = Object.entries(attr);
for (const [k,v] of map) elm[k] = v;
return elm;
};
//nodeTypeの確認
const isElementNode = n => n ? n.nodeType===1 : false;
//子孫要素の追加
const childAppender = (...elms) => {
const idx = elms.findIndex(x => !isElementNode(x));
switch (idx) {
case -1: break;
case 0: return null;
case 1: return elms[0];
default: elms.slice(0, idx); break;
}
for (let i=0,len=elms.length-1; i<len; i++) {
elms[i].appendChild(elms[i + 1]);
}
return elms[0];
};
//兄弟要素の追加
const siblingAppender = (parent, ...elms) => {
if (!isElementNode(parent)) return null;
const available = elms.filter(isElementNode);
for (const child of available) parent.appendChild(child);
return parent;
};
##関数の説明
-
el( tagName[, {attribute: value,...}] )
要素を生成し返す。
引数1:tagName => HTMLのタグ名
引数2:属性名をKEY、値をVALUEで組んだオブジェクト形式
elm.className = 'classname'のようなイコールで指定出来るもののみ
elm.classList.add('classname')のような指定方法のものは不可 -
childAppender( element1, element2, ... )
第一引数を親要素として残りの引数を順次、直列的に子孫に追加し、親要素を返す。
nodeTypeが1でない要素が存在すると以降の要素は追加されない。 -
siblingAppender( parentNode, element1, element2, ... )
第一引数を親要素として残りの引数を順次、兄弟要素として親要素の直下に追加し、親要素を返す。
nodeTypeが1でない要素は追加されないが、childAppenderと違い最後の引数まで追加される。
#感想
少し重い気がする。