JavaScript | 1 日 60 分 × 7 日アプリ学習:初級編

APP JavaScript
スポンサーリンク

この 7 日・60 分でどこまで行くか

この「初級編・60 分 × 7 日」は、すでに

  • console.log
  • 変数・if・関数・配列
  • 簡単なおみくじやボタン付きアプリ

あたりを「なんとなく触ったことがある」前提で進めます。

この 7 日間のゴールはこうです。

  • ブラウザ上で動く「ToDo(やること)アプリ」を、自分で一から組み立てられる
  • ページを閉じても残るように、localStorage で保存までできる
  • コードの「流れ」と「役割分担(HTML / CSS / JS)」を自分で説明できる

1 日 60 分なので、
前半 30 分は「読む+写経」、後半 30 分は「自分で少し改造して遊ぶ」が理想です。


Day 1: 環境づくりと「アプリの骨組み」を作る

開発環境をシンプルに整える

特別なツールは不要です。

  • ブラウザ(Chrome / Edge など)
  • テキストエディタ(VSCode やメモ帳でも可)

フォルダを一つ作り、その中に次の 3 ファイルを作ります。

  • index.html
  • style.css
  • app.js

これで「本物の Web アプリと同じ構成」になります。

最小の HTML を書く

index.html に次を書いてください。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>やることリスト</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <h1>やることリスト</h1>

    <input id="todo-input" type="text" placeholder="やることを入力">
    <button id="add-btn">追加</button>

    <div id="todo-list"></div>

    <script src="app.js"></script>
  </body>
</html>
JavaScript

ここで押さえたいことは 3 つです。

  • <input> が「やること」を入力する場所
  • <button> が「追加」ボタン
  • <div id="todo-list"> が「リストを表示する場所」

<link> で CSS、<script> で JavaScript を読み込んでいます。
これが「画面(HTML)+見た目(CSS)+動き(JS)」の基本形です。

CSS と JS をつないで動作確認

style.css にとりあえず次を書きます。

body {
  font-family: sans-serif;
}

app.js には次を書きます。

console.log("app.js 読み込み OK");
JavaScript

index.html をブラウザで開き、開発者ツールの Console を見ると
「app.js 読み込み OK」と出ていれば準備完了です。


Day 2: DOM をつかまえて、ボタンから動きをつける

DOM 要素を JavaScript で取得する

app.js を次のように書きます。

const input = document.getElementById("todo-input");
const addButton = document.getElementById("add-btn");
const list = document.getElementById("todo-list");

console.log(input);
console.log(addButton);
console.log(list);
JavaScript

ブラウザで開いて Console を見ると、
それぞれの要素が表示されます。

ここが超重要ポイントです。

  • document は「ページ全体」を表すオブジェクト
  • getElementById("…") は、HTML の id="…" を持つ要素を 1 つ取ってくる
  • 取ってきた要素に対して、後で「中身を変える」「イベントをつける」ができる

この「HTML に id をつける → JS で getElementById する」は何度も出てきます。

クリックイベントを設定する

次に、ボタンがクリックされた瞬間を「つかまえる」コードを書きます。

addButton.addEventListener("click", function () {
  console.log("ボタンが押されました");
});
JavaScript

ブラウザでボタンを押すたびに、Console にメッセージが出れば OK です。

ここで理解してほしいのは、

  • addEventListener("click", ...)
    「クリックされたときに、この関数を実行して」という登録
  • function () { ... } の中身が「起きてほしい動き」

という構造です。

入力欄の値を取る

イベントの中で、入力された文字を取り出してみます。

addButton.addEventListener("click", function () {
  const text = input.value;
  console.log("入力されたテキスト:", text);
});
JavaScript

input.value が「フォームに入力された文字列」です。
フォーム系では、この value を扱えるかどうかが重要です。


Day 3: 画面に ToDo を追加していく

要素を作って、DOM に追加する

ボタンを押したとき、「入力された文字を画面に追加」するコードを書きます。

app.js のイベント内を次のように変えます。

addButton.addEventListener("click", function () {
  const text = input.value;

  if (text === "") {
    return;
  }

  const item = document.createElement("p");
  item.textContent = text;

  list.appendChild(item);

  input.value = "";
});
JavaScript

流れを分解して説明します。

  • document.createElement("p")
    JavaScript 上で新しい <p> 要素を「まだ画面にない状態で」作る
  • item.textContent = text;
    その要素の中身の文字を設定する
  • list.appendChild(item);
    #todo-list の中に子要素として追加する → ここで画面に現れる
  • input.value = "";
    入力欄を空に戻して、次の入力がしやすいようにする

ここでは innerHTML ではなく textContent を使っています。
textContent は「そのまま文字として」、innerHTML は「HTML として解釈」されるので、
初級のうちは textContent を優先する方が安全です。

簡単なスタイルを付けて読みやすくする

style.css に次を追加します。

#todo-input {
  padding: 8px;
  font-size: 16px;
}

#add-btn {
  padding: 8px 16px;
  font-size: 16px;
  margin-left: 4px;
}

#todo-list p {
  margin: 4px 0;
}
JavaScript

これで見た目が少し整って、アプリ感が出てきます。
「見た目が整うと、コードのやる気も上がる」ので、CSS はちょこちょこ足していきます。


Day 4: 配列で「状態」を持ち、画面を再描画するパターン

状態(データ)と表示(DOM)を分ける

今は、「ボタンが押されるたびに DOM を直接いじる」形です。
これでも動きますが、削除機能などが増えると管理が大変になります。

そこで、次の考え方に変えます。

  • ToDo の中身は「配列」で管理(=状態)
  • 画面は「配列の中身を見て描画」する

この分離が、アプリ開発においてめちゃくちゃ重要です。

状態配列と render 関数を導入する

app.js を少し書き換えます。

ファイルの上の方に次を追加します。

const input = document.getElementById("todo-input");
const addButton = document.getElementById("add-btn");
const list = document.getElementById("todo-list");

const todos = [];
JavaScript

そして、新しく render 関数を作ります。

function render() {
  list.textContent = "";

  for (let i = 0; i < todos.length; i++) {
    const item = document.createElement("p");
    item.textContent = todos[i];
    list.appendChild(item);
  }
}
JavaScript

クリックイベントをこう書き換えます。

addButton.addEventListener("click", function () {
  const text = input.value;

  if (text === "") {
    return;
  }

  todos.push(text);

  render();

  input.value = "";
});
JavaScript

ここで深掘りしたいポイントは次です。

  • todos が「本当のデータの置き場」
  • render は、「配列の中身 → DOM に描画する」役
  • クリック時は「配列を更新 → render()」という流れ

この「状態と描画の分離」を体で覚えると、
後で React / Vue / Svelte などに進むときもスムーズです。


Day 5: 削除機能を追加し、「ちょっと複雑な動き」に慣れる

各 ToDo に削除ボタンを付ける

render 関数を次のように書き換えます。

function render() {
  list.textContent = "";

  for (let i = 0; i < todos.length; i++) {
    const wrapper = document.createElement("div");
    wrapper.className = "todo-item";

    const item = document.createElement("span");
    item.textContent = todos[i];

    const delButton = document.createElement("button");
    delButton.textContent = "削除";

    delButton.addEventListener("click", function () {
      todos.splice(i, 1);
      render();
    });

    wrapper.appendChild(item);
    wrapper.appendChild(delButton);

    list.appendChild(wrapper);
  }
}
JavaScript

流れを整理します。

  • <div class="todo-item"> で 1 行分を包む
  • <span> にテキストを入れ、
    <button> に「削除」と表示
  • 削除ボタンが押されたとき
    • todos.splice(i, 1) で「i 番目の要素を 1 個削除」
    • その後 render() で画面を描き直す

ここで大事なのは、

  • 「配列から消す」→「画面を再描画する」
  • 直接 DOM から消すのではなく、「状態を変えてから描画し直す」

という発想です。
これに慣れると、アプリの処理が一気に見通しやすくなります。

削除ボタンの見た目を整える

style.css に次を追加します。

.todo-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 300px;
  margin: 4px auto;
  padding: 4px 8px;
  border-bottom: 1px solid #ddd;
}

.todo-item button {
  padding: 2px 8px;
  font-size: 12px;
}

「横並びになって、右に小さな削除ボタン」という、よくある UI になります。
ここまで来ると、かなり「それっぽい」アプリになっているはずです。


Day 6: localStorage で「ページを閉じても残るアプリ」にする

localStorage のイメージ

localStorage はブラウザに備わっている「超簡単な保存箱」です。

  • キー(名前)と値(文字列)をセットで保存できる
  • ブラウザを閉じても残る
  • 同じドメインの同じページから何度でも取り出せる

ただし、「文字列しか保存できない」がポイントです。
今回の todos は配列なので、そのままでは保存できません。

そこで、

  • 配列 → JSON 文字列に変換して保存
  • 取り出すときに JSON 文字列 → 配列に復元

という流れを取ります。

保存関数と読み込み処理を追加する

app.js に次の関数を追加します。

function save() {
  const json = JSON.stringify(todos);
  localStorage.setItem("todos", json);
}
JavaScript

JSON.stringify が「配列 → JSON 文字列」の変換です。

クリックイベントと削除部分を少し変更します。

addButton.addEventListener("click", function () {
  const text = input.value;

  if (text === "") {
    return;
  }

  todos.push(text);

  save();
  render();

  input.value = "";
});
JavaScript

削除ボタン内も同じく、render() の前後で save() を呼びます。

delButton.addEventListener("click", function () {
  todos.splice(i, 1);
  save();
  render();
});
JavaScript

さらに、ページを開いたときに保存済みデータを読み込みます。

function load() {
  const json = localStorage.getItem("todos");
  if (json === null) {
    return;
  }

  const array = JSON.parse(json);
  todos.length = 0;
  for (let i = 0; i < array.length; i++) {
    todos.push(array[i]);
  }
}

load();
render();
JavaScript

ここで深掘りしたいポイントはこうです。

  • localStorage.setItem("キー", "文字列") で保存
  • localStorage.getItem("キー") で取得(なければ null
  • JSON.stringify(配列) で保存用の文字列に変換
  • JSON.parse(文字列) で配列に戻す

これができれば、「ページを閉じても残るアプリ」を作れるようになります。


Day 7: コードを整理して「自分で読める」状態にする

コード全体を見渡して、役割を言語化する

ここまでの app.js は、ざっくり次のブロックに分かれます。

  • DOM 要素の取得(getElementById
  • 状態(todos 配列)
  • 描画関数(render
  • 保存関数(save)、読み込み関数(load
  • イベント設定(addButton.addEventListener など)

1 行ずつ意味を追いながら、「これは何のためのコードか」を自分の言葉で説明してみてください。
ここまでできれば、「コピペしているだけの人」からは完全に卒業です。

仕上げとして、ちょっとだけ機能を足してみる

例えば、今日やってみるといい小さな改造は次のようなものです。

  • Enter キーでも追加できるようにする
    • input.addEventListener("keydown", function (event) { ... })
  • 空白だけの入力は追加しないようにする
    • text.trim() === "" をチェック
  • タイトルを「◯◯のやることリスト」に変えてみる

どれか一つでも、自分の手で「仕様を考えて → コードを書いて → 動かしてみる」までできれば、
この 7 日間の成果としては十分すぎるくらいです。


この先のおすすめルート

この 7 日で身についたのは、初級としてかなり強い力です。

  • DOM 操作
  • イベント処理
  • 配列での状態管理
  • render パターン
  • localStorage での簡易保存

次の 7 日をやるなら、例えばこんなテーマがあります。

  • 同じパターンで「簡易メモ帳アプリ」を作る
  • カウントアップ+リセット付き「筋トレカウンター」アプリ
  • タイマー(setInterval / setTimeout)を使ったアプリ

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