初めに
ただの記録です。
Reactに移る前のコードと移った後のコードを貼っているだけ。
VanilaなJavaScriptでの記載
移行前の前(createElementを多用)
document.createElement
をひたすら使ってるパターンです
bodyの中身が全部tdでいいならさらにmapでいいんですが、
各カラムで別々の何かを適用させたい場合はひたすら変数が増えていくパターン...(嫌すぎる)
See the Pen Untitled by sinsky (@sky-sora) on CodePen.
コード(codepenの内容と一緒です)
<div id="root"></div>
window.addEventListener("DOMContentLoaded", () => {
// 使用するデータ
// https://www.tiobe.com/tiobe-index/
const tableData = {
head: ["Aug 2022", "Aug 2021", "Change", "Programming Language", "Ratings", "Change"],
body: [
[1, 2, "up", "Python", 15.42, "+3.56"],
[2, 1, "down", "C", 14.59, "+2.03"],
[3, 3, "", "Java", 12.40, "+1.96"],
[4, 4, "", "C++", 10.17, "+2.81"],
[5, 5, "", "C#", 5.59, "+0.45"],
[6, 6, "", "Visual Basic", 4.99, "0.33"],
[7, 7, "", "JavaSCript", 2.33, "-0.61"],
[8, 9, "up", "Assembly language", 2.17, "+0.14"],
[9, 10, "up", "SQL", 1.70, "+0.23"],
[10, 8, "down", "PHP", 1.39, "-0.80"]
],
};
const root = document.querySelector("#root");
const table = document.createElement("table");
const thead = document.createElement("thead");
const thead_tr = document.createElement("tr");
tableData.head.map(title => {
const th = document.createElement("th");
th.innerHTML = title;
thead_tr.append(th);
});
thead.append(thead_tr);
table.append(thead);
const tbody = document.createElement("tbody");
tableData.body.map(row => {
const tr = document.createElement("tr");
const [year, lastYear, change, lang, rate, diff] = row;
const year_td = document.createElement("td");
year_td.innerHTML = year;
tr.append(year_td);
const lastYear_td = document.createElement("td");
lastYear_td.innerHTML = lastYear;
tr.append(lastYear_td);
const change_td = document.createElement("td");
change_td.innerHTML = change;
tr.append(change_td);
const lang_td = document.createElement("td");
lang_td.innerHTML = lang;
tr.append(lang_td);
const rate_td = document.createElement("td");
rate_td.innerHTML = rate;
tr.append(rate_td);
const diff_td = document.createElement("td");
diff_td.innerHTML = diff;
tr.append(diff_td);
tbody.append(tr);
});
table.append(tbody);
root.append(table);
})
移行前(templateを利用する)
document.importNode
を利用して、HTMLに先に記載しているTemplateを使うやり方です
一つ前のやり方よりも、こっちの方がclassの定義とかを前もってできるので、
わざわざJavaScriptで書き換える必要がないというメリットがあります。
これを知ってからはcreateElement
を使うことは無くなりました(HTMLでclassとかdata属性を管理したかったので)
See the Pen use template by sinsky (@sky-sora) on CodePen.
コード(codepenの内容と一緒です)
<div id="root">
<table id="table">
<thead></thear>
<tbody></tbody>
</table>
</div>
<template id="table-head">
<tr>
<th data-id="year"></th>
<th data-id="lastYear"></th>
<th data-id="change"></th>
<th data-id="lang"></th>
<th data-id="rate"></th>
<th data-id="diff"></th>
</tr>
</template>
<template id="table-body">
<tr>
<td data-id="year"></td>
<td data-id="lastYear"></td>
<td data-id="change"></td>
<td data-id="lang"></td>
<td data-id="rate"></td>
<td data-id="diff"></td>
</tr>
</template>
window.addEventListener("DOMContentLoaded", () => {
// 使用するデータ
// https://www.tiobe.com/tiobe-index/
const tableData = {
head: ["Aug 2022", "Aug 2021", "Change", "Programming Language", "Ratings", "Change"],
body: [
[1, 2, "up", "Python", 15.42, "+3.56"],
[2, 1, "down", "C", 14.59, "+2.03"],
[3, 3, "", "Java", 12.40, "+1.96"],
[4, 4, "", "C++", 10.17, "+2.81"],
[5, 5, "", "C#", 5.59, "+0.45"],
[6, 6, "", "Visual Basic", 4.99, "0.33"],
[7, 7, "", "JavaSCript", 2.33, "-0.61"],
[8, 9, "up", "Assembly language", 2.17, "+0.14"],
[9, 10, "up", "SQL", 1.70, "+0.23"],
[10, 8, "down", "PHP", 1.39, "-0.80"]
],
};
const table_head_content = document.querySelector("#table-head").content;
const head_fragment = document.createDocumentFragment();
const head_clone = document.importNode(table_head_content, true);
const [year, lastYear, change, lang, rate, diff] = tableData.head;
head_clone.querySelector("[data-id='year']").innerHTML = year;
head_clone.querySelector("[data-id='lastYear']").innerHTML = lastYear;
head_clone.querySelector("[data-id='change']").innerHTML = change;
head_clone.querySelector("[data-id='lang']").innerHTML = lang;
head_clone.querySelector("[data-id='rate']").innerHTML = rate;
head_clone.querySelector("[data-id='diff']").innerHTML = diff;
head_fragment.append(head_clone);
document.querySelector('#table > thead').appendChild(head_fragment);
// 長いから関数作ってみる
const getId = (clone, id) => clone.querySelector(`[data-id='${id}']`);
const table_body_content = document.querySelector("#table-body").content;
const body_fragment = document.createDocumentFragment();
tableData.body.map(row => {
const body_clone = document.importNode(table_body_content, true);
const [year, lastYear, change, lang, rate, diff] = row;
getId(body_clone, "year").innerHTML = year;
getId(body_clone, "lastYear").innerHTML = lastYear;
getId(body_clone, "change").innerHTML = change;
getId(body_clone, "lang").innerHTML = lang;
getId(body_clone, "rate").innerHTML = rate;
getId(body_clone, "diff").innerHTML = diff;
body_fragment.append(body_clone);
});
document.querySelector('#table > tbody').appendChild(body_fragment);
});
Reactで書く
面倒になったのでコードだけな上に一つのコードにまとめています(しかもexportして終わり)
const Thead = ({ data }) => {
const [year, lastYear, change, lang, rate, diff] = data;
return (
<thead>
<tr>
<th>{year}</th>
<th>{lastYear}</th>
<th>{change}</th>
<th>{lang}</th>
<th>{rate}</th>
<th>{diff}</th>
</tr>
</thead>
);
};
const Tbody = ({ data }) => {
return (
<tbody>
{data.map((row) => {
const [year, lastYear, change, lang, rate, diff] = row;
return (
<tr>
<td>{year}</td>
<td>{lastYear}</td>
<td>{change}</td>
<td>{lang}</td>
<td>{rate}</td>
<td>{diff}</td>
</tr>
);
})}
</tbody>
);
};
export const App = () => {
const tableData = {
head: ["Aug 2022", "Aug 2021", "Change", "Programming Language", "Ratings", "Change"],
body: [
[1, 2, "up", "Python", 15.42, "+3.56"],
[2, 1, "down", "C", 14.59, "+2.03"],
[3, 3, "", "Java", 12.4, "+1.96"],
[4, 4, "", "C++", 10.17, "+2.81"],
[5, 5, "", "C#", 5.59, "+0.45"],
[6, 6, "", "Visual Basic", 4.99, "0.33"],
[7, 7, "", "JavaSCript", 2.33, "-0.61"],
[8, 9, "up", "Assembly language", 2.17, "+0.14"],
[9, 10, "up", "SQL", 1.7, "+0.23"],
[10, 8, "down", "PHP", 1.39, "-0.80"],
],
};
return (
<table>
<Thead data={tableData.head} />
<Tbody data={tableData.body} />
</table>
);
};
終わりに
こんな感じで移行したんだよってお話でした。
document.importNode
に慣れていたからか、
React(JSX)の方にも違和感なく書き換えることができました。
document.createElement
の多用は何も考えずにJavaScriptだけ弄っていればいいので楽なんですが、
最終的なHTMLが想像しづらい上に、classなどの管理も非常に面倒だったなぁと書きながら思い出していました。
React言わずもがなですね。。。
Vanillaは気軽なモックを作るときにとてもお手軽なので、
Node.jsが使えない環境の時はとてもありがたいんですよね。
(CDNはBabelも導入しないとJSXが書けなかったり、CDNが業務上ネットワークでブロックされていたり(思い出したくない記憶))...
忘れないための備忘録的な意味も含めての投稿でした。