テンプレート文字列で HTML を作る意味
テンプレート文字列はバッククォートで囲み、${...} に式を埋め込めるため、“見た目どおり”に HTML 断片を組み立てられます。ここが重要です:複数行とインデントをそのまま保持でき、タグの並びや改行がコードに直接現れるので、従来の文字列連結より圧倒的に読みやすく、ミスを減らせます。
const title = "商品一覧";
const header = `
<section class="hero">
<h1>${title}</h1>
<p>ようこそ!</p>
</section>
`;
JavaScript基本パターン(複数行+式を使った組み立て)
その場で整形して埋め込む
表示用の数値や日付は、${...} の中でフォーマットしてから挿入します。ここが重要です:テンプレートは“見た目”、整形ロジックは“関数”へ分離すると保守性が上がります。
const yen = n => `${n.toLocaleString("ja-JP")} 円`;
const card = ({ id, name, price }) => `
<div class="card" data-id="${id}">
<h2>${name.trim()}</h2>
<p>価格: ${yen(price)}</p>
</div>
`;
console.log(card({ id: 1, name: " Apple ", price: 123456 }));
JavaScript条件を埋め込む
短い条件は三項演算子や論理演算子で“式”として挿入します。
const badge = onSale => `${onSale ? '<span class="badge">SALE</span>' : ""}`;
const row = ({ id, price, onSale }) => `
<tr>
<td>${id}</td>
<td>${price.toLocaleString("ja-JP")} 円 ${badge(onSale)}</td>
</tr>
`;
JavaScript配列とテンプレートの相性(リスト・テーブル生成)
map と join で量産する
ここが重要です:配列の map で各要素の HTML を作り、最後に join(“”) で一つの文字列へ連結します。改行を含めたい場合は要素内に改行を書きます。
const items = [
{ id: 1, name: "Apple", price: 100, onSale: true },
{ id: 2, name: "Banana", price: 200, onSale: false },
];
const table = `
<table class="items">
<thead>
<tr><th>ID</th><th>商品名</th><th>価格</th></tr>
</thead>
<tbody>
${items.map(i => `
<tr class="${i.onSale ? "sale" : ""}">
<td>${i.id}</td>
<td>${i.name}</td>
<td>${i.price.toLocaleString("ja-JP")} 円</td>
</tr>
`).join("")}
</tbody>
</table>
`;
console.log(table);
JavaScriptネストした構造も分割して組み立てる
大きなテンプレートは“部分テンプレート”に分けて合成すると読みやすくなります。
const rowHtml = i => `
<tr>
<td>${i.id}</td>
<td>${i.name}</td>
<td>${i.price.toLocaleString("ja-JP")} 円</td>
</tr>
`;
const tbodyHtml = rows => rows.map(rowHtml).join("");
const tableHtml = rows => `
<table>
<thead><tr><th>ID</th><th>商品名</th><th>価格</th></tr></thead>
<tbody>${tbodyHtml(rows)}</tbody>
</table>
`;
JavaScript安全対策(サニタイズと属性の扱い)
ユーザー入力は必ずエスケープする
ここが重要です:テンプレート文字列は“文字列をそのまま差し込む”ので、ユーザー入力を直接 HTML に埋め込むと XSS の危険があります。最低限、< > & " ' をエスケープしましょう。
const escapeHtml = s => String(s).replace(/[&<>"']/g, c => ({
"&": "&", "<": "<", ">": ">", '"': """, "'": "'"
}[c]));
const renderComment = ({ user, text }) => `
<div class="comment">
<span class="user">${escapeHtml(user)}</span>
<p>${escapeHtml(text)}</p>
</div>
`;
console.log(renderComment({ user: "<Alice>", text: `こんにちは "世界"` }));
JavaScript属性値・data-* で安全に渡す
イベントハンドラ文字列を直接埋め込まず、data-* 属性に値を入れて、後から JS で処理する方が安全で保守しやすいです。
const button = ({ id, label }) => `
<button class="buy" data-id="${id}">${escapeHtml(label)}</button>
`;
// 生成後にイベントを紐づける例(DOM 使用時)
/*
document.body.innerHTML += button({ id: 7, label: "購入" });
document.querySelectorAll(".buy").forEach(btn => {
btn.addEventListener("click", e => {
const id = e.currentTarget.dataset.id;
console.log("buy id:", id);
});
});
*/
JavaScriptインデントと改行の扱い(見た目を保つ)
テンプレート文字列は改行・空白をそのまま保持します。ここが重要です:視認性のためにコードをインデントすると、その空白も出力に含まれます。必要なら“デデント(インデント除去)”や trim() を使って整えます。
const raw = `
<ul>
<li>A</li>
<li>B</li>
</ul>
`;
const clean = raw.trim(); // 先頭・末尾の改行や空白を落とす
console.log(clean);
JavaScriptデデント用のタグ付きテンプレートを使うと、コードのインデントを保ちながら出力は左端に揃えられます。
function dedent(strings, ...vals) {
let text = strings.reduce((o, s, i) => o + s + (vals[i] ?? ""), "");
text = text.replace(/^\n+/, "").replace(/\n+$/, "\n");
const lines = text.split("\n");
const min = Math.min(...lines.filter(l => l.trim()).map(l => l.match(/^(\s*)/)[1].length));
return lines.map(l => l.slice(min)).join("\n");
}
const html = dedent`
<div>
<h1>Title</h1>
<p>Body</p>
</div>
`;
console.log(html);
JavaScriptパフォーマンスと設計のコツ(重要ポイントの深掘り)
複雑なロジックをテンプレート内に詰め込みすぎると読みづらく、遅くなります。ここが重要です:整形は関数へ分離、配列は map+join、重い計算は事前に変数へ。部分テンプレートを合成して“大枠→パーツ”の順に組むと、差分更新やテストが容易になります。非同期データを埋め込むときは、テンプレートを返す関数自体を async にして await を使います。
const fetchJson = async url => (await fetch(url)).json();
async function productTable() {
const rows = await fetchJson("/api/products");
return `
<section>
<h1>Products</h1>
${tableHtml(rows)}
</section>
`;
}
JavaScript実用例で理解を固める
// 1) カード一覧
const cardList = items => `
<div class="cards">
${items.map(card).join("")}
</div>
`;
console.log(cardList([
{ id: 1, name: "Apple", price: 100 },
{ id: 2, name: "Banana", price: 200 }
]));
// 2) 検索フォーム+結果テーブル
const form = (q = "") => `
<form id="search">
<input name="q" value="${escapeHtml(q)}" placeholder="キーワード" />
<button>検索</button>
</form>
`;
const page = (q, rows) => `
${form(q)}
${tableHtml(rows)}
`;
console.log(page("js 入門", items));
// 3) メール本文(HTML)
const mailHtml = ({ to, body }) => `
<!doctype html>
<html lang="ja">
<body>
<p>こんにちは、${escapeHtml(to)} さん</p>
<div>${escapeHtml(body).replace(/\n/g, "<br>")}</div>
</body>
</html>
`;
console.log(mailHtml({ to: "Alice", body: "ご連絡ありがとうございます。\n詳細は後ほど" }));
JavaScriptまとめ
HTML 生成におけるテンプレート文字列の核心は「バッククォートで複数行とインデントを自然に書き、${...} に式・整形・条件を埋め込む」ことです。配列は map+join、部分テンプレートに分けて合成、ユーザー入力は必ずエスケープ、属性と data-* を活用、改行・空白は必要に応じて整える。これを徹底すれば、初心者でも見た目とロジックをきれいに分離した、読みやすく安全な HTML を ES6+ で組み立てられます。
