テンプレートリテラルでHTML生成を最適化

「文字列の結合が多くて見づらい…」

「HTMLのエスケープ処理って毎回どうすればいいんだろう?」

「バッククォートは使ってるけど、本当に正しく使えてるのかな」

前回はアロー関数とthisの振る舞いについて学びました。今回は、HTMLの生成をより簡潔に、安全に行うためのテンプレートリテラルについて解説します。

なぜテンプレートリテラルが必要か

まず、従来のHTML生成方法を振り返ってみましょう:

JS
// jQuery時代のHTML生成
var userHtml = '';
userHtml += '<div class="user-card">';
userHtml += '  <h2>' + user.name + '</h2>';
userHtml += '  <p class="email">' + user.email + '</p>';
userHtml += '  <p class="bio">' + user.bio + '</p>';
userHtml += '</div>';

$('#userList').append(userHtml);

この方法の問題点:

  • 文字列結合が煩雑
  • インデントが分かりにくい
  • エスケープ処理が漏れやすい
  • 可読性が低い

テンプレートリテラルの基本

JS
// モダンな書き方
const userHtml = `
    <div class="user-card">
        <h2>${user.name}</h2>
        <p class="email">${user.email}</p>
        <p class="bio">${user.bio}</p>
    </div>
`;

document.querySelector('#userList').innerHTML = userHtml;

テンプレートリテラルの特徴:

  • バッククォート(`)で囲む
  • 複数行の記述が可能
  • 式の埋め込みが${…}で簡単に
  • HTMLの構造が視覚的に理解しやすい

実践的な使い方

1. 条件分岐の組み込み

JS
const cardHtml = `
    <div class="user-card ${user.isAdmin ? 'admin' : ''}">
        <h2>${user.name}</h2>
        ${user.isAdmin ? `
            <span class="badge">管理者</span>
        ` : ''}
        <p class="email">${user.email}</p>
    </div>
`;

ポイント:

  • 三項演算子で条件分岐を表現
  • 入れ子のテンプレートリテラルも可能
  • クラスの動的な追加が簡単

2. 繰り返し処理

JS
const users = [
    { name: 'John', email: 'john@example.com' },
    { name: 'Jane', email: 'jane@example.com' }
];

const userListHtml = `
    <ul class="user-list">
        ${users.map(user => `
            <li class="user-item">
                <strong>${user.name}</strong>
                <span>${user.email}</span>
            </li>
        `).join('')}
    </ul>
`;

ポイント:

  • map関数で配列を処理
  • join(”)で配列を結合
  • インデントが維持され可読性が高い

3. ヘルパー関数の活用

JS
const escape = str => str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');

const userProfile = `
    <div class="profile">
        <h2>${escape(user.name)}</h2>
        <p>${escape(user.bio)}</p>
    </div>
`;

セキュリティ対策:

  • XSS対策としてエスケープ処理
  • ヘルパー関数で共通化
  • 必要な箇所のみエスケープ

タグ付きテンプレート

JS
// タグ関数の定義
function html(strings, ...values) {
    return strings.reduce((result, str, i) => {
        const value = values[i - 1];
        // 値がある場合はエスケープ処理
        return result + (i > 0 ? escape(value) : '') + str;
    });
}

// 使用例
const userCard = html`
    <div class="user-card">
        <h2>${user.name}</h2>
        <p>${user.bio}</p>
    </div>
`;

タグ付きテンプレートの利点:

  • 自動的なエスケープ処理
  • 値の加工や検証が可能
  • 再利用可能な処理

コンポーネント化の例

JS
class UserCard {
    constructor(user) {
        this.user = user;
    }
    
    render() {
        return `
            <div class="user-card">
                ${this.renderHeader()}
                ${this.renderBody()}
                ${this.renderFooter()}
            </div>
        `;
    }
    
    renderHeader() {
        return `
            <header>
                <h2>${escape(this.user.name)}</h2>
            </header>
        `;
    }
    
    renderBody() {
        return `
            <div class="card-body">
                <p>${escape(this.user.bio)}</p>
            </div>
        `;
    }
    
    renderFooter() {
        return `
            <footer>
                <a href="mailto:${escape(this.user.email)}">
                    連絡する
                </a>
            </footer>
        `;
    }
}

コンポーネント化のメリット:

  • テンプレートの再利用が容易
  • 責務の分割が明確
  • メンテナンス性の向上

パフォーマンスの最適化

JS
// テンプレートの事前コンパイル
const template = values => `
    <div class="user-card">
        <h2>${values.name}</h2>
        <p>${values.bio}</p>
    </div>
`;

// 大量のデータを処理する場合
const fragment = document.createDocumentFragment();

users.forEach(user => {
    const div = document.createElement('div');
    div.innerHTML = template(user);
    fragment.appendChild(div.firstChild);
});

document.querySelector('#userList').appendChild(fragment);

最適化のポイント:

  • テンプレート関数の再利用
  • DocumentFragmentの活用
  • 必要最小限のDOM操作

まとめ

テンプレートリテラルを使うことで:

  • HTML生成が直感的に
  • メンテナンス性が向上
  • セキュリティ対策が容易に
  • コードの構造化が簡単に

次回は「クラス構文で整理する – オブジェクト指向プログラミングの現代的アプローチ」について解説し、より大規模なアプリケーション開発の手法を学んでいきましょう。