MVCは何ですか?


初めてWeb開発に触れた時、MVC、MVT、MVVMなど多様なパターンが存在すると聞きました.しかし、各パターンがなぜ生まれたのか、正確には何なのか分からない.
この機会に知っておくべき部分を整理しておきます.

Why MVC?


Model, View, Controller
MVCが登場したきっかけは簡単だった.これは人類が開発をより便利かつ効率的にするために発売した設計モデルの一つである.
コンピュータエンジニアリングでは,設計モードはプログラム開発でよく発生する問題を解決するために設計された特定の方法である.通常、構造的な問題の解決に大きな役割を果たす.
簡単に言えば、やったことを繰り返し、余計な内容を加えないなど、きれいに開発するために生まれたのです.これは過去の開発者たちが作った秘訣であり、その重さは無視できない.

Model


これらには、全体的なデータのフォーマット、データがどのように格納されるか、データがどのようにロードされるかなどが含まれます.
モデルはデータの構成にのみ関心を持つ.これらのデータをどのように処理するか、ユーザーにどのように表示するかは、人々が関心を持っている問題ではありません.

View


「ビューは、ユーザーに直接表示される部分です.」コントローラによってロードされたデータをユーザーに表示します.
ビューは、モデルやコントローラがどのように動作するかにも関心がありません.自分が受け取ったデータをレンダリングすることだけを気にします.

Controller


コントローラはビューとモデルにコマンドを発行します.
コントローラは、名前に基づいてビューとモデルを制御します.ユーザ(クライアント)がビューを介してリクエストを生成すると、コントローラはリクエストを受け取り、モデルに渡します.
モデルが要求を実行し、新しい値を返すと、コントローラはビューに通知します.次に、ビューは新しい応答に基づいて画面を再編成します.
コントローラは、各レイヤで何が起こっているのかを理解するために、各レイヤを調整する必要があります.


文字だけでは感じられないので、自分で表現することにしました.簡単なリスト形式でフォームを提出するときに追加し、リストをクリックすると機能のワークピースを削除します.


// model.js

export const db = {
};

export class Post {
  constructor(id, title, author, content) {
    this.id = id;
    this.title = title;
    this.author = author;
    this.content = content;
  }

  static writePost(post) {
    db[post.id] = post;
  }

  static deletePost(id) {
    delete db[id];
  }
}
モデルのファイルを設定します.dbという変数を使用してstateを表し、各属性を持つPostオブジェクトを格納します.
// view.js

export function render(state, target) {
  target.innerHTML = Object.keys(state)
    .map(
      (id) =>
        `<li class='post' data-id=${id}>
        <div class="meta">
            <span class='title'>${state[id].title}</span>
            <span class='author'>${state[id].author}</span>
        </div>
        <span class='content'>${state[id].content}</span>
    </li>`
    )
    .join("");
}
レンダリングを担当するviewファイル.入力パラメータのstateに基づいて、li要素をinnerHTMLとしてターゲットパラメータに配置します.
// controller.js

import { db, Post } from "./model.js";
import { render } from "./view.js";

function init() {
  const posts = document.querySelector(".posts");

  setEventHandler();
  render(db, posts);
}

function setEventHandler() {
  const submitForm = document.querySelector(".form");
  const posts = document.querySelector(".posts");

  submitForm.addEventListener("submit", (e) => {
    e.preventDefault();

    const [title, author, content] = [
      e.target[0].value,
      e.target[1].value,
      e.target[2].value,
    ];

    const post = new Post(new Date().getTime(), title, author, content);
    Post.writePost(post);

    render(db, posts);
    e.target.reset();
  });

  posts.addEventListener("click", (e) => {
    const id = e.target.closest("li").dataset.id;
    Post.deletePost(id);

    render(db, posts);
  });
}

init();
HTMLファイルに直接接続されたコントロールファイル.各機能にイベントハンドラを設定し、発生したイベントごとにviewのレンダリング関数を実行します.
やりすぎたような気がします:<
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script type="module" src="./controller.js" defer></script>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div class="root">
      <ul class="posts"></ul>
      <form class="form">
        <div class="meta">
          <input class="title" name="title" type="text" placeholder="제목" />
          <input
            class="author"
            name="author"
            type="text"
            placeholder="작성자"
          />
        </div>
        <textarea class="content" name="content" placeholder="내용"></textarea>
        <button type="submit">제출</button>
      </form>
    </div>
  </body>
</html>
index.htmlファイル.初期レンダリング後のコントローラ.jsの調整に伴い、画面構造が変化します.

ポスト


やってみましたが、まだ確定していません.もう一度探してみると、viewで固定された値だけを処理してレンダリングし、流れの値はモデルで処理し、controllerで渡されます.
ではhtmlファイル自体に触れるべきではありませんか?rootコンテナのみを作成し、残りの固定値をビューに渡すことが望ましい.