タグ関数とは
HTMLのテンプレートを引数に渡す目的で実装された関数のことです。
以下のコードでは、tagFunction がタグ関数に該当します。
const view = tagFunction`
<div>${hoge}と${fuga}</div>
`;
function tagFunction(strings, ...values) {
console.log(strings);
console.log(...values);
}
タグ関数について調べた背景
JSPrimerでタグ関数を学習していた際、
上記のようなタグ関数の引数をコンソールに出力した際に、配列が出力された
第一引数(strings) の出力結果
0: "↵ <div>
1: "と"
2: "</div>↵"
第二引数(...values) の出力結果
hoge fuga
この時
Q. どういうルールで、第一引数に入る配列が作成されるのか
Q. タグ関数を呼び出す際、引数にはHTMLテンプレート1つしか渡していないのに、第二引数に値が入るのはなぜか
という疑問を持ったので、調べてみました。
タグ関数の呼び出し方
タグ関数を呼び出す時は、通常の関数と違い
関数`テンプレート`;
という書き方をします。
一般的な関数呼び出しは
関数(引数);
と書きます。
使い方
実際のコードだと以下のように使います。
escapeHTML がタグ関数に該当します。
const view = escapeHTML`
<h4>${userInfo.name} (@${userInfo.login})</h4>
<img src="${userInfo.avatar_url}" alt="${userInfo.login}" height="100">
<dl>
<dt>Location</dt>
<dd>${userInfo.location}</dd>
<dt>Repositories</dt>
<dd>${userInfo.public_repos}</dd>
</dl>
`;
function escapeHTML(strings, ...values) {
return strings.reduce((result, str, i) => {
const value = values[i - 1];
if (typeof value === "string") {
return result + escapeSpecialChars(value) + str;
} else {
return result + String(value) + str;
}
});
}
userInfoの定義
githubのユーザ情報が格納されており、各プロパティの詳細は以下の通りです。
userInfo.name:ユーザ名
userInfo.login:ログイン名
userInfo.avatar_url:プロフィール画像
userInfo.location:住んでいる国名
userInfo.public_repos:パブリックリポジトリの数
それでは、背景で書いた疑問の解答を書いていきます。
疑問1つ目
Q. どういうルールで、HTMLのテンプレートが区切られて、配列へ格納されるのか
A. テンプレートリテラル内の${value}
が区切りとなり、それぞれが一要素として配列へ格納されます
配列をコンソールに出力すると、以下が表示されました。
(7) ["↵ <h4>", " (@", ")</h4>↵ <img src="", "" alt="", "" height="100">↵ <dl>↵ <dt>Location</dt>↵ <dd>", "</dd>↵ <dt>Repositories</dt>↵ <dd>", "</dd>↵ </dl>↵ ", raw: Array(7)]
0: "↵ <h4>"
1: " (@"
2: ")</h4>↵ <img src=""
3: "" alt=""
4: "" height="100">↵ <dl>↵ <dt>Location</dt>↵ <dd>"
5: "</dd>↵ <dt>Repositories</dt>↵ <dd>"
6: "</dd>↵ </dl>↵ "
疑問2つ目
Q. タグ関数を呼び出す際、引数にはHTMLテンプレート1つしか渡していないのに、第二引数に値が入るのはなぜか
A. valuesには、テンプレートリテラル内の${value}
の実際の値が格納された配列が入るため
第二引数(...values) もコンソールに出力すると、以下が表示されました。
null "bita-kodai" "プロフィール画像のURL" "bita-kodai" null 17
終わりに
最後までご覧頂きありがとうございます。
何か補足や疑問点、フィードバック等々ございましたら、コメント欄への記載をお願いします。