何をしたいユーティリティか:「パンくず生成」
ここでの「パンくず生成」は、
「今いるページまでの階層(ホーム > マスタ > ユーザー一覧 > ユーザー詳細)」を、決まったルールで文字列や配列として作る」ユーティリティです。
画面の上に出ている、あの「階層ナビゲーション」です。
業務システムでは、画面数が増えるほど「自分がどこにいるか」が分かりにくくなるので、
パンくずをきちんと設計しておくと、使い勝手が一気に良くなります。
パンくずに必要な情報を整理する
1 要素に持たせたい情報
パンくずの 1 つ 1 つは、だいたい次の 2 つを持っています。
- 表示名(例:
"ホーム","マスタ","ユーザー一覧") - リンク先 URL(例:
"/","/masters","/masters/users")
一番右の「現在ページ」はリンクなしにすることが多いですが、
データ構造としては「全部リンク付き」で持っておき、
表示側で「最後だけリンクを外す」という実装にするのが扱いやすいです。
パンくずの「型」を決める
型イメージ
JavaScript では、パンくずはこんな配列で表現できます。
const breadcrumbs = [
{ label: "ホーム", path: "/" },
{ label: "マスタ", path: "/masters" },
{ label: "ユーザー一覧", path: "/masters/users" },
{ label: "ユーザー詳細", path: "/masters/users/123" },
];
JavaScriptこの「配列の形」をユーティリティの出力として固定してしまえば、
あとはフレームワーク側(React / Vue など)で自由に描画できます。
一番シンプルな「手動指定」パンくず生成
配列をそのまま返す関数
まずは、「呼び出し側で配列を組んで、それを返すだけ」の超シンプル版です。
function buildBreadcrumb(items) {
if (!Array.isArray(items)) {
return [];
}
return items.map((item) => ({
label: String(item.label ?? ""),
path: item.path ?? null,
}));
}
JavaScript重要なポイント
items が配列でなければ空配列を返すようにして、
呼び出し側のミスで落ちないようにしています。
label は必ず文字列に変換し、path は null を許容しています(リンクなしの要素も表現できるように)。
この関数自体は単純ですが、
「パンくずはこの形で扱う」というルールをコードで固定する役割があります。
ルート定義からパンくずを組み立てる
ルート情報を「マスタ」として持つ
業務システムでは、URL と画面名の対応をどこかにまとめておくと便利です。
例えば、こんな「ルート定義」を用意します。
const ROUTES = {
home: { label: "ホーム", path: "/" },
masters: { label: "マスタ", path: "/masters" },
users: { label: "ユーザー一覧", path: "/masters/users" },
userDetail: { label: "ユーザー詳細", path: "/masters/users/:id" },
};
JavaScriptここで大事なのは、「キー(home, masters など)」でルートを識別していることです。
URL が変わっても、このマスタだけ直せば済むようにしておきます。
ルートキーの配列からパンくずを作る
例えば、「ユーザー詳細」画面のパンくずは、
homemastersusersuserDetail
という順番のルートキーで表せます。
これをユーティリティに渡して、パンくず配列を作ります。
function buildBreadcrumbFromRouteKeys(routeKeys, params = {}) {
if (!Array.isArray(routeKeys)) {
return [];
}
const items = [];
for (const key of routeKeys) {
const route = ROUTES[key];
if (!route) continue;
const label = route.label;
const path = route.path ? fillPathParams(route.path, params) : null;
items.push({ label, path });
}
return items;
}
JavaScriptここで fillPathParams は、"/masters/users/:id" の :id を実際の値で置き換える小さな関数です。
パスパラメータを埋める小さな関数
:id などを実際の値に置き換える
function fillPathParams(path, params) {
if (!path || !params) return path;
return path.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {
const value = params[key];
return value != null ? encodeURIComponent(String(value)) : "";
});
}
JavaScript重要なポイント
/:id のような部分を正規表現で見つけて、params.id の値で置き換えています。
encodeURIComponent を通しているので、
ID に記号が入っていても URL として安全な形になります。
実際の動きを例で確認する
ユーザー詳細画面のパンくず
const routeKeys = ["home", "masters", "users", "userDetail"];
const params = { id: 123 };
const breadcrumbs = buildBreadcrumbFromRouteKeys(routeKeys, params);
JavaScriptbreadcrumbs の中身はこうなります。
[
{ label: "ホーム", path: "/" },
{ label: "マスタ", path: "/masters" },
{ label: "ユーザー一覧", path: "/masters/users" },
{ label: "ユーザー詳細", path: "/masters/users/123" },
]
JavaScriptあとは、フロント側で
- 最後の要素だけリンクなしで表示
- それ以外は
<a href="...">で表示
というルールで描画すれば、きれいなパンくずになります。
パンくず文字列として組み立てるユーティリティ
「表示用文字列」だけ欲しい場合
ログやタイトルなどで、「パンくずを 1 本の文字列として使いたい」こともあります。
その場合は、配列から文字列を作る関数を用意します。
function breadcrumbToString(breadcrumbs, separator = " > ") {
if (!Array.isArray(breadcrumbs)) {
return "";
}
const labels = breadcrumbs.map((b) => b.label).filter((x) => x);
return labels.join(separator);
}
JavaScript実際の動き
const text = breadcrumbToString(breadcrumbs);
// "ホーム > マスタ > ユーザー一覧 > ユーザー詳細"
JavaScriptこれをそのままログに出したり、
HTML タイトルに混ぜたりすることもできます。
実務で意識してほしい設計のポイント
「パンくずはルート定義から作る」を徹底する
画面ごとに、
const breadcrumbs = [
{ label: "ホーム", path: "/" },
{ label: "マスタ", path: "/masters" },
...
];
JavaScriptとベタ書きし始めると、
画面名や URL を変更したときに、全画面を探して直すことになります。
ルート定義(ROUTES)を 1 箇所にまとめ、
パンくずは「ルートキーの配列」から作る、という形にしておくと、
仕様変更に強くなります。
「どこまでをパンくずに出すか」を決める
業務システムでは、階層が深くなりすぎると、
パンくずが長くなりすぎて逆に見づらくなることがあります。
例えば、
- ホーム
- 受注管理
- 受注一覧
- 受注詳細
- 明細編集
まで全部出すのか、
「受注一覧」までにしておくのか、
「受注詳細」までにしておくのか。
この「深さのルール」も、
ルート定義やルートキーの配列でコントロールできるようにしておくと、
あとから調整しやすくなります。
パラメータをタイトルに含めるかどうか
"ユーザー詳細 #123" のように、
ID をパンくずに含めるかどうかも設計ポイントです。
含める場合は、ROUTES.userDetail.label を固定文字列ではなく、
関数にしてしまう方法もあります。
const ROUTES = {
userDetail: {
label: (params) => `ユーザー詳細 #${params.id}`,
path: "/masters/users/:id",
},
};
JavaScriptそして、buildBreadcrumbFromRouteKeys 側で、
const label = typeof route.label === "function"
? route.label(params)
: route.label;
JavaScriptのように呼び分ければ、
「ID 付きのラベル」をパンくずに出せます。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを実際に打ってみてください。
const routeKeys = ["home", "masters", "users", "userDetail"];
const params = { id: 123 };
const breadcrumbs = buildBreadcrumbFromRouteKeys(routeKeys, params);
breadcrumbs;
breadcrumbToString(breadcrumbs);
JavaScript配列の中身と、文字列の結果を見て、
- ラベルとパスが期待通りか
- パスパラメータが正しく埋まっているか
- 文字列のパンくずが自然か
を確認してみてください。
そのうえで、自分のプロジェクトに
export const ROUTES = { ... };
export function buildBreadcrumbFromRouteKeys(...) { ... }
export function breadcrumbToString(...) { ... }
JavaScriptのような形で置き、
「パンくずが欲しくなったら、必ずこの“パンくず生成ユーティリティ”を通す」
というルールを作ってみてください。
それだけで、あなたのシステムのパンくずは、場当たり的な配列ベタ書きから、
意図と一貫性を備えた「業務レベルのナビゲーション設計」に変わっていきます。

