JavaScript | 1 日 90 分 × 7 日アプリ学習:強化版カウンターアプリ(初級編)

JavaScript
スポンサーリンク

3日目のゴールと今日のテーマ

3日目のテーマは「昨日までのカウンターを“拡張しやすい設計”に進化させること」です。
初級編とはいえ、ここから一気に「アプリとしての設計力」が伸びます。

今日のゴールはこうです。

複数ボタンを追加しても壊れない設計を理解する。
イベント分離をさらに徹底して、コードの見通しを良くする。
数値管理を“1か所”に閉じ込めて、どこからでも扱いやすくする。
+1 / −1 / リセット / 0未満防止を、より洗練された形で扱えるようにする。

1日目・2日目で作ったカウンターを、
「強化版カウンターの土台」に仕上げる日です。


まずは昨日までの構造を“設計目線”で振り返る

状態(state)と画面(view)の分離

昨日までで、あなたはすでにこの構造を作れています。

let count = 0;

function render() {
  counterEl.textContent = count;
}
JavaScript

これは実は、アプリ設計の超重要パターンです。

状態(count)は JavaScript が持つ。
画面(HTML)は状態を映すだけ。

この分離ができていると、アプリが大きくなっても混乱しません。

changeCount にロジックを集めたのが大正解

昨日の changeCount はこうでした。

function changeCount(delta) {
  const next = count + delta;

  if (next < 0) {
    return;
  }

  count = next;
  render();
}
JavaScript

ここに「0未満防止」や「状態更新+render」が集まっています。

つまり、

「count を変えるときのルールはここに全部ある」

という状態です。

この“ロジックの集約”が、今日の強化の中心になります。


3日目のテーマ:ボタンが増えても壊れない設計

もしボタンが増えたらどうなる?

例えば、今日からこういうボタンを追加したいとします。

+5
−5
+10
−10

昨日までの設計なら、こう書くだけで済みます。

function handlePlus5() {
  changeCount(5);
}

function handleMinus5() {
  changeCount(-5);
}
JavaScript

なぜこんなに簡単なのか?

理由は、

「数値を変えるロジックが changeCount に集まっているから」

です。

もし changeCount がなかったら、
各ボタンに「0未満防止」「render」などを全部書く必要があり、
コードが一気に崩壊します。


イベント分離をさらに“美しく”する

ボタンのイベント登録をまとめる

昨日はこう書いていました。

plusButton.addEventListener("click", handlePlus);
minusButton.addEventListener("click", handleMinus);
resetButton.addEventListener("click", handleReset);
JavaScript

これでも十分ですが、
ボタンが増えるとイベント登録が増えていきます。

そこで、3日目では「イベント登録をまとめる」考え方を紹介します。

data-属性を使ってイベントをまとめる(初級でも理解できる)

HTML をこうしておきます。

<button data-delta="1">+1</button>
<button data-delta="-1">−1</button>
<button data-delta="5">+5</button>
<button data-delta="-5">−5</button>
<button id="btn-reset">リセット</button>

JavaScript 側ではこう書けます。

const buttons = document.querySelectorAll("button[data-delta]");

buttons.forEach((btn) => {
  btn.addEventListener("click", () => {
    const delta = Number(btn.dataset.delta);
    changeCount(delta);
  });
});
JavaScript

これで、

+1
−1
+5
−5

すべてのボタンが「1つのイベント処理」で動きます。

なぜこれが強いのか?

理由は2つあります。

1つ目:ボタンが増えても JavaScript を書き足す必要がない。
2つ目:イベント処理が1か所にまとまって、コードが読みやすい。

初級の段階でこの設計を理解できると、
中級・上級に進んだときに圧倒的に有利です。


数値管理を“もっと安全に”する

changeCount をさらに強化する

昨日の changeCount はこうでした。

function changeCount(delta) {
  const next = count + delta;

  if (next < 0) {
    return;
  }

  count = next;
  render();
}
JavaScript

今日は、これをもう少しだけ強化します。

1. 上限値を入れられるようにする(発展)

例えば、最大 100 までにしたい場合。

const MAX = 100;

function changeCount(delta) {
  const next = count + delta;

  if (next < 0 || next > MAX) {
    return;
  }

  count = next;
  render();
}
JavaScript

これで、

0未満禁止
100超え禁止

の両方が changeCount に集まります。

2. ルールを1か所に集めるメリット

ルールが1か所にあると、

「アプリの仕様を変えたいとき、どこを直せばいいかが明確」

になります。

例えば、

「0未満禁止 → −10 まではOKにしたい」
「上限100 → 上限200にしたい」

などの変更が、changeCount だけで完結します。


3日目のミニ課題:ボタンを増やしても壊れないカウンター

今日の完成イメージ

+1
−1
+5
−5
リセット

これらが全部動き、
0未満防止
上限値(任意)
イベント分離
数値管理の集約

ができている状態です。

コードの全体像(イメージ)

let count = 0;
const MAX = 100;

const counterEl = document.getElementById("counter");
const resetButton = document.getElementById("btn-reset");

function render() {
  counterEl.textContent = count;
}

function changeCount(delta) {
  const next = count + delta;

  if (next < 0 || next > MAX) {
    return;
  }

  count = next;
  render();
}

function setup() {
  render();

  const buttons = document.querySelectorAll("button[data-delta]");
  buttons.forEach((btn) => {
    btn.addEventListener("click", () => {
      const delta = Number(btn.dataset.delta);
      changeCount(delta);
    });
  });

  resetButton.addEventListener("click", () => {
    count = 0;
    render();
  });
}

setup();
JavaScript

この構造は、初級のうちに身につけておくと本当に強いです。


3日目のまとめと、4日目へのつなぎ

今日やったことを整理します。

複数ボタンを「data-属性」でまとめて扱う方法を学んだ。
イベント分離をさらに徹底し、イベント登録を1か所に集めた。
changeCount を強化し、0未満防止+上限値などのルールを1か所に集約した。
ボタンが増えても壊れない、拡張しやすい設計を体験した。

4日目では、ここからさらに

複数カウンターを同時に動かす
カウンターごとに独立した状態を持たせる
「オブジェクトで状態を管理する」

という、アプリ設計の次のステップに進みます。

最後にひとつだけ。

今日の中で、「あ、これ設計として気持ちいいな」と感じた部分はどこでしたか。
data-属性でイベントをまとめた瞬間か、changeCount にルールを集めた瞬間か。
その“気持ちよさ”が、あなたの設計センスの核になります。

タイトルとURLをコピーしました