正在載入索引…

JavaScript:注重關注點的分離

2.0k 字,約 2 分鐘

文章目錄
  1. 定義
  2. 關注點分離- MVC 概念

🌟 關注點分離(Separation of Concerns,SoC)


定義

  • 關注點分離是一種軟體設計原則,將一個系統劃分為不同的模組或元件,每個模組或元件集中於解決特定的關注點或任務,以提高系統的可操作性、可維護性、可擴展性和可重用性。該原則主張將不同層面的關注點獨立開發,使得修改一個關注點不會影響其他關注點。
  • 傳統的網頁開發中,通常會將網頁的開發區分為 HTML、CSS、JavaScript 三個技術領域,並分別將它們拆分成不同的檔案,以負責各自的領域。
    • HTML: 語意層,負責網頁結構和整體語意。
    • CSS: 樣式層,負責網頁外觀和樣式。
    • JavaScript: 邏輯層,負責處理事件邏輯和動態行為。
  • 避免寫行內樣式(inline style)跟行內腳本(inline script)造成彼此領域的干涉。
html
<h1 style="color:red;font-size:46px;"  onclick="alert('Hi')">
  Hello World
</h1>

  • 關注點分離寫法
  • HTML(語意層):
html
<h1>
  Hello World
</h1>
  • CSS(樣式層)
css
h1 {
  color: red;
  font-size: 46px;
}
  • JavaScript(邏輯層)
javascript
// script.js
document.addEventListener('DOMContentLoaded', function () {
  const header = document.querySelector('h1');
  header.addEventListener('click', function () {
    alert('Hi');
  });
});

關注點分離- MVC 概念

  • Model:
    • 負責處理數據的邏輯,包括數據的存儲、檢索、更新和刪除等操作。
  • View:
    • 負責呈現界面,即用戶界面的渲染和顯示。
  • Controller:
    • 負責接收用戶的輸入,處理業務邏輯,然後更新模型和視圖。

  • 單純依賴 Controller 影響 View 的節點,使得 View 上呈現的節點難以維護。

我們希望透過 MVC 的概念讓維護上更為方便。

  • 使用者與介面互動 -> Controller 處理網頁邏輯 -> Controller 調用 Model 方法,影響 Model 資料(新增或修改) -> 修改完 Controller 再次呼叫 View 渲染的方法 -> View 根據更新後的資料重新渲染
  • 達到 View 及 Model 透過 Controller 進行彼此的溝通而不直接互相影響。
  • 透過以下流程搭配程式碼進行說明
    1. 用戶與界面互動,觸發 Controller 的相應方法。
      • 使用者在瀏覽器點擊移除。
    2. Controller 根據用戶的輸入操作 Model。
      • 按鈕的點擊事件觸發了 removeData 方法,這是 Controller 中的一個相應方法。
    3. Model 的狀態發生變化。
      • removeData 方法中使用了 splice 方法來移除資料陣列 data 中的特定項目,即刪除了一個資料項。
    4. Controller 得知 Model 狀態的變化,通知相應的 View。
      • removeData 方法執行完畢後,立即呼叫了 render 方法,這是通知 View 部分。
    5. View 從 Model 中獲取最新的數據。
      • render 方法內部重新遍歷資料陣列,創建新的 HTML 元素,並更新 DOM 中的內容。
    6. View 使用這些數據更新界面。
      • 新的 HTML 元素被注入到 DOM 中,此時界面上的列表已經更新,反映了資料變化。
在 CodePen 開啟

程式碼:

javascript
const component = {
  // Model的部分
  // --------
  data: [
    '這是第一句話',
    '這是第二句話',
    '這是第三句話'
  ],
  removeData(id) {
    this.data.splice(id, 1);
    this.render();
  },
  // --------

  // View的部分
  // --------
  renderList() {
    const list = document.querySelector('.component ul');
    let content = '';
    this.data.forEach((item, i) => {
      content = `${content}<li>${item} <button type="button" class="btn" data-id="${i}">移除</button></li>`;
    });
    list.innerHTML = content;
  },
  addEventListeners() {
    const btns = document.querySelectorAll('.btn');
    btns.forEach(btn => btn.addEventListener('click', (e) => {
      const id = e.target.dataset.id;
      this.removeData(id);
    }));
  },
  // --------

  // Controller
  // --------
  render() { // 渲染方法
    this.renderList();
    this.addEventListeners();
  },
  init() {
    this.render();
  }
  // --------
};
component.init();

留言

留言使用 GitHub 帳號登入(Giscus),留言會存在 GitHub Discussions。