JavaScriptで商品管理アプリを作って学んだこと
はじめに
HTML / CSS / JavaScriptの学習として、商品管理アプリを作成しました。
今回の目的は、JavaScriptの文法を単体で覚えるだけではなく、複数の処理を組み合わせて1つの作品を完成させることです。
作ったもの
商品名と価格を登録して、一覧で管理できるアプリです。
主な機能
- 商品登録
- 入力チェック
- 商品検索
- 個別削除
- 全削除
- 合計金額の表示
- localStorageへの保存
- ページ再読み込み後のデータ復元
使用技術
- HTML
- CSS
- JavaScript
- localStorage
- JSON
苦戦したこと
1. 処理を書く場所
イベントの中に書く処理と、外に関数として書く処理の区別に苦戦しました。
特に検索処理や描画処理を最初はイベントの中に書いていましたが、複数の場所から使えるように関数へ分けました。
2. データとDOMの違い
商品を削除するとき、
-
products配列から削除する - 画面上の商品一覧を更新する
この2つは別の処理だと理解しました。
そこで、
- データを変更する
- localStorageへ保存する
- 合計を更新する
- 一覧を再描画する
という流れに整理しました。
3. 処理の関数化
同じ処理が増えてきたため、以下のように関数へ分けました。
-
saveProducts():保存 -
loadProducts():読み込み -
updateTotal():合計更新 -
updateDisplay():検索条件で絞り込み -
renderProducts():商品一覧を描画
この整理をしたことで、追加・削除・検索の処理が分かりやすくなりました。
localStorageへの保存
商品データは配列として管理しています。
保存するときは、JSON.stringify() を使って文字列に変換してから保存しました。
function saveProducts() {
localStorage.setItem("products", JSON.stringify(products));
}
読み込むときは、JSON.parse() を使ってJavaScriptの配列へ戻しました。
function loadProducts() {
let savedProducts = localStorage.getItem("products");
if (savedProducts !== null) {
products = JSON.parse(savedProducts);
}
}
localStorageには文字列として保存されるため、JSON.stringify() と JSON.parse() を使っています。
検索機能
検索欄に入力された文字を取得して、filter() と includes() を使って商品を絞り込みました。
function updateDisplay() {
let keyword = searchInput.value.toLowerCase();
let filteredProducts = products.filter(function (product) {
return product.name.toLowerCase().includes(keyword);
});
renderProducts(filteredProducts);
}
検索欄が空の場合は includes("") が true になるため、すべての商品が表示されます。
商品一覧の描画
表示処理は renderProducts() にまとめました。
function renderProducts(productArray) {
productList.textContent = "";
productArray.forEach(function (product) {
let item = document.createElement("li");
item.textContent = product.name + ":" + product.price + "円";
let button = document.createElement("button");
button.textContent = "削除";
button.classList.add("deleteButton");
button.addEventListener("click", function () {
products = products.filter(function (itemProduct) {
return itemProduct !== product;
});
saveProducts();
updateTotal();
updateDisplay();
});
item.append(button);
productList.append(item);
});
}
描画前に、
productList.textContent = "";
として一度一覧を空にし、そのあと最新のデータを使って描画しています。
合計金額の更新
商品の価格を forEach() で合計しました。
function updateTotal() {
let sum = 0;
products.forEach(function (product) {
sum = sum + product.price;
});
total.textContent = "合計" + sum + "円";
}
商品追加
商品追加時は、
- 入力内容を取得
- 入力チェック
- オブジェクトを作成
-
products配列へ追加 - 保存
- 合計更新
- 表示更新
という流れにしました。
addButton.addEventListener("click", function () {
let value = nameInput.value;
let price = priceInput.value;
let number = Number(price);
if (value === "") {
message.textContent = "商品名を入力してください";
} else if (price === "") {
message.textContent = "価格を入力してください";
} else if (Number.isNaN(number)) {
message.textContent = "数字を入力してください";
} else {
let product = {
name: value,
price: number
};
products.push(product);
saveProducts();
message.textContent = "追加しました";
nameInput.value = "";
priceInput.value = "";
nameInput.focus();
updateTotal();
updateDisplay();
}
});
全削除機能
全削除では products を空配列にして、その状態を保存しました。
clearButton.addEventListener("click", function () {
products = [];
saveProducts();
updateTotal();
updateDisplay();
});
学んだこと
今回の制作を通して、特に以下を学びました。
- DOM操作
addEventListener()- 配列とオブジェクト
filter()forEach()includes()toLowerCase()- 関数化
- localStorage
JSON.stringify()JSON.parse()- 検索結果の再描画
- データとDOMの違い
- データを変更してから画面を更新する考え方
単体の文法を覚えるだけでなく、複数の知識を組み合わせて実装することの難しさを実感しました。
Demo
GitHub
おわりに
今回が、GitHub Pagesまで公開した最初のJavaScript作品になりました。
最初は処理を書く場所や、イベントの中と外、関数化の考え方でかなり迷いました。
しかし、最終的には、
データを変更
↓
保存
↓
合計更新
↓
表示更新
という流れで整理できるようになりました。
次は別のJavaScript作品を作り、今回学んだ内容を自力で使えるようにしていきたいです。