オブジェクトを使って、絞り込み機能付きの商品リストを作ります。
キーワード:オブジェクト
作成例(完成イメージ)
- 作成例:https://ngsm-syr.github.io/javascript_object/
- コード:https://github.com/ngsm-syr/javascript_object/
下記の順番で進めます。
- HTMLで基本の文書構造を作る
- CSSでUIを整える
- JavaScriptでオブジェクトを定義する(作例の場合は商品リスト)
- 具体的な処理を関数として記述する
- JavaScriptでイベントの発生条件を設定をする(クリック時)
【準備】フォルダ:javascript_object
①JavaScriptを書くための準備で作成したフォルダ(空のHTML、CSS、JavaScriptが入っている)を準備します。GitHubからもダウンロードできます。
②フォルダの名前を「javascript_object」に変更します
③同じサイズの画像を4〜6枚程度用意します。作例と同じ画像を使う方は、GitHubからダウンロードしてください。
画像は images フォルダに入れます。
HTMLの準備
まず、コンテンツ部分を用意します。
▼index.html
<header>
<h1>My Select Shop</h1>
</header>
<main>
<div class="buttons">
<button id="show-all">全て表示</button>
<button id="filter-price">2,000円以下の商品</button>
<button id="filter-stock">在庫ありのみ</button>
</div>
<div id="product-container">
</div>
</main>
▼style.css
body {
font-family: sans-serif;
background-color: #f8f8f8;
}
h1 {
text-align: center;
}
.buttons {
text-align: center;
margin-bottom: 20px;
}
button {
padding: 8px 16px;
margin: 0 5px;
cursor: pointer;
border: 1px solid #ddd;
border-radius: 8px;
}
#product-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
}
.card {
width: 220px;
background: white;
border-radius: 8px;
text-align: center;
padding: 15px;
}
.card img {
max-width: 100%;
height: 150px;
object-fit: contain;
}
.card h2 {
font-size: 1.2em;
margin: 10px 0;
}
.price {
font-weight: bold;
color: #e91e63;
}
footer {
text-align: center;
}
オブジェクトを定義する
▼script.js
const products = [
{ name: '商品1', price: 1800, image: 'images/img01.png', inStock: true },
{ name: '商品2', price: 3500, image: 'images/img02.png', inStock: false },
{ name: '商品3', price: 1200, image: 'images/img03.png', inStock: true },
{ name: '商品4', price: 2100, image: 'images/img04.png', inStock: true }
];
console.log('商品配列:', products);
console.log('商品数:', products.length);
console.log('1番目の商品:', products[0]);
console.log('1番目の商品名:', products[0].name);
console.logを記述することで中身を確認します。
【参考】オブジェクト
変数を管理する入れ物。1つの「モノ」に関する情報を、ひとまとめにしたデータのことです。下記のように、{ } で囲まれた部分をオブジェクトリテラルと呼び、1つ分のオブジェクトを指します。
{ name: '商品1', price: 1800, image: 'images/img01.png', inStock: true }
今回の作例では、商品ごとのオブジェクトを作成し、商品名、値段、画像、在庫有無の情報をひとまとめにしています。複数のオブジェクトを[ ]でまとめ、配列にしています。[ ] は配列リテラルと呼びます。
HTMLの各要素を取得(定数の定義)
▼script.js
const productContainer = document.getElementById('product-container');
const showAllBtn = document.getElementById('show-all');
const filterPriceBtn = document.getElementById('filter-price');
const filterStockBtn = document.getElementById('filter-stock');
オブジェクトの情報を表示する
▼script.js(上記の定数宣言の下に記載)
// --- 関数:商品の配列を受け取って、画面にカードを表示する ---
function displayProducts(productArray) {
productContainer.innerHTML = ''; // 表示エリアを一度空にする
productArray.forEach(product => {
// 在庫状況に応じて表示を変える
const stockStatus = product.inStock ? '在庫あり' : '在庫なし';
// カードのHTMLを文字列として組み立てる
const cardHTML = `
<div class="card">
<img src="${product.image}" alt="${product.name}">
<h2>${product.name}</h2>
<p class="price">¥${product.price.toLocaleString()}</p>
<p class="stock">${stockStatus}</p>
</div>
`;
// 組み立てたHTMLをコンテナに追加
productContainer.insertAdjacentHTML('beforeend', cardHTML);
});
}
//←ここにイベントを追加
displayProducts(products); // 初期表示
【参考】三項演算子
?は三項演算子(条件演算子)です。
条件 ? 真の場合の値 : 偽の場合の値
下記のように使用しています。
const stockStatus = product.inStock ? '在庫あり' : '在庫なし';
product.inStockをチェックtrueなら'在庫あり'を返すfalseなら'在庫なし'を返す
同じ処理をif文で書くと次のようになります。三項演算子は短くことができ、条件によって値を決める場面でよく使用されます。
let stockStatus;
if (product.inStock) {
stockStatus = '在庫あり';
} else {
stockStatus = '在庫なし';
}
【参考】insertAdjacentHTML()
insertAdjacentHTMLは、指定されたテキストを HTMLとして「挿入」することができます。HTMLの挿入は、innerHTMLでもできますが、innerHTMLは、既にあるHTMLを削除した上で再構築をかけるのに対し、insertAdjacentHTMLは、挿入処理のみを行います。
【参考】テンプレートリテラル
テンプレートリテラルを使うと、変数の値を文字列に挿入することができます。
「``内で変数を${ } で囲う」ことで使用できます。記号` は、バッククォート(逆引用符)です。
【参考】引数(ひきすう)
ここで定義しているdisplayProducts()という関数は引数を受け取って処理されています。引数とは、関数を実行するときに渡される値のことです。( ) の中に記載します。
displayProducts(products);
引数を使うことで、この後設定する絞り込み機能に対応し、件数を変更した配列の表示にも対応できるようにしています。
→引数を使った例:https://nagashima.kyusan-u.ac.jp/note/javascript-basic02/
イベントの設定(動作のきっかけを作る)
addEventListener()を使って、動作を引き起こすためのイベントを設定します。
▼script.js
//←ここにイベントを追加
showAllBtn.addEventListener('click', () => {
displayProducts(products); // 全ての商品データをそのまま表示
});
displayProducts(products); // 初期表示
イベントの設定(価格の絞り込み)
価格で商品を絞り込む機能を追加します。
▼script.js(全データ表示のイベントの下に記述)
filterPriceBtn.addEventListener('click', () => {
// filterを使って、価格が2000円以下の商品だけを絞り込む
const cheapProducts = products.filter(p => p.price <= 2000);
displayProducts(cheapProducts); // 絞り込んだ結果を表示
});
displayProducts(products); // 初期表示
【参考】filter
filterとは配列メソッドで、条件に合う要素だけを抽出して新しい配列を作ります。
配列.filter(条件関数)
今回の例では、下記のような処理を行っています。
const cheapProducts = products.filter(p => p.price <= 2000);
products配列の各要素をpとして順次チェックp.price <= 2000がtrueなら新しい配列に含めるfalseなら除外
pは<p>要素ではなく変数名です。ここではproducts配列の各要素を表す変数として使っています。自由に決められる変数名です。
イベントの設定(在庫の絞り込み)
在庫の有無で商品を絞り込む機能を追加します。
▼script.js(価格の絞り込みのイベントの下に記述)
filterStockBtn.addEventListener('click', () => {
// filterを使って、在庫がある商品だけを絞り込む
const stockProducts = products.filter(p => p.inStock === true);
displayProducts(stockProducts); // 絞り込んだ結果を表示
});
displayProducts(products); // 初期表示
【参考】オブジェクト部分を外部ファイル化する
オブジェクトは.json(JavaScript Object Notation:ジェイソン)ファイルとして、外部ファイルにすることもできます。外部ファイルを読み込む処理を追加することで、使用できます。なお外部ファイルの読み込みは、ローカル環境(file:///...)では動作しません。Visual Studio Codeの場合は、Live Serverなどを使って、ローカルサーバーで確認してください。
参考書籍・リンク
- 「独習JavaScript」CodeMafia 外村将大, 翔泳社, 2021
- https://developer.mozilla.org/ja/docs/Web/API/Element/innerHTML
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
- https://developer.mozilla.org/ja/docs/Web/API/Element/insertAdjacentHTML
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Template_literals
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter