つくる ひとことメモウィジェット
このレッスンで分かること
- 追加も削除も、まず配列を変えてから一覧をまるごと描き直します
- 配列を変えた場所すべてで保存すると、メモがリロードをまたいで残ります
2 件目を消したはずが、3 件目が消える
削除ボタンを作るとき、押された li をその場で画面から取り除く書き方を思い付きます。1 件だけなら動きます。ところが 2 件目を消したあと、残った 3 件目のボタンを押すと、まるで違うものが消えます。ボタンが覚えている番号は作ったときのままなのに、画面の並びだけが 1 つ詰まったからです。
画面を直接いじって帳尻を合わせようとすると、件数の表示も、削除ボタンの番号も、すぐにずれます。逃げ道は 1 つです。本物は配列のほうで、画面はそれを写したものと決めてしまいます。追加でも削除でも、やることは「配列を変える」「配列から一覧を作り直す」の 2 手だけになります。
今回はこの形でひとことメモのウィジェットを作ります。新しい文法はほとんど足しません。第5章の配列、第6章の関数、第8章の組み立て、第9章のイベント、前回の保存を 1 か所に合流させるだけです。決まりは次のとおりです。
- 作品とお問い合わせのあいだにメモの
sectionを足し、入力欄・追加ボタン・案内文・一覧・件数を id で用意する - メモの配列を持ち、読み込み時に保存から読み戻す。読めないときや保存が無いときは空の配列にする
- 一覧を作り直す関数を 1 本用意し、1 件ごとに
liと削除ボタンを作って件数も入れる - 追加ボタンは入力欄の値を
trim()して配列に足し、入力欄を空にする。空のときは追加せず案内文を出す - 追加と削除のどちらでも、配列を変えたあとに保存する
描き直しは、先に空にしてから
描き直す関数は、いちばん最初に中身を捨てるところから始めます。ここを忘れると、呼ぶたびに古い一覧の下へ積み上がっていきます。
JavaScript
const tags = ["HTML", "CSS", "JavaScript"];
tagList.textContent = "";
tags.forEach(function (tag, index) {
const item = document.createElement("li");
item.textContent = index + " 番目 " + tag;
tagList.appendChild(item);
});forEach の第 2 引数 index が、その要素が配列の何番目かです。削除ボタンをこの中で作れば、ボタンの処理から index を見られます。関数の中から外側の変数を見られるのは、第6章でやったとおり、関数が書かれた場所の変数を覚えているからです。
配列から 1 件だけ抜くのは splice です。第 2 引数を省くと、その位置から後ろが全部消えてしまうので必ず 2 つ書きます。
JavaScript
tags.splice(1, 1);
console.log(tags); // ["HTML", "JavaScript"]抜いたあとに描き直す関数をもう一度呼べば、番号は振り直され、残ったボタンは正しい番号を持ち直します。冒頭の「3 件目が消える」が起きなくなるのは、この一手のおかげです。
配列を変えたら、その場で保存する
保存は前回と同じ形です。配列はそのままでは入らないので JSON.stringify を通し、読むときに JSON.parse で戻します。読めなかったときに空の配列を返しておけば、以降の処理は「まだ 1 件も無い」ときと同じに書けます。
JavaScript
try {
const saved = localStorage.getItem("tags");
const parsed = saved === null ? [] : JSON.parse(saved);
console.log(Array.isArray(parsed) ? parsed : []);
} catch (error) {
console.log([]);
}Array.isArray で確かめているのは、保存された文字列が壊れていたり、別の形が入っていたときの用心です。
呼ぶ順番は、読み出してから描く、です。配列を先に用意し、最後に描き直す関数を 1 回呼べば、前回のメモが並んだ状態でページが始まります。配列を受ける変数は const でかまいません。push や splice で中身は変えても、入れ物そのものを別の配列に取り替えることはないからです。
よくある間違い
- 保存を書き忘れる場所がある — 追加のときだけ保存して削除で忘れると、消したはずのメモがリロードで復活します。配列を変える行の直後は必ず保存、と手癖にしてください
- 描き直す前に空にし忘れる — 追加するたびに一覧が二重、三重に増えていきます。関数の 1 行目で
textContentを空にします - 空のまま追加できてしまう —
trim()を通さないと、スペースだけのメモが作れてしまいます。読んだ直後に落とします
課題
- 作品とお問い合わせのあいだにメモの section を足す。入力欄 memo-input、追加ボタン memo-add、案内文 memo-message、一覧 memo-list、件数 memo-count を id で用意する
- メモの配列を持ち、loadMemos で localStorage から読み戻す。読めないときや保存が無いときは空の配列にする
- renderMemos 関数で一覧を作り直す。1 件ごとに li と削除ボタンを作り、memo-count に件数を入れる。削除ボタンは splice で 1 件だけ抜く
- 追加ボタンを押したら入力欄の値を trim して配列に足し、入力欄を空にして描き直す。空のときは追加せず memo-message に入力をうながす文を出す
- 追加と削除のどちらでも、配列を変えたあとに JSON.stringify で保存する