JavaScript:注重關注點的分離
2.0k 字,約 2 分鐘
文章目錄
🌟 關注點分離(Separation of Concerns,SoC)
定義
- 關注點分離是一種軟體設計原則,將一個系統劃分為不同的模組或元件,每個模組或元件集中於解決特定的關注點或任務,以提高系統的可操作性、可維護性、可擴展性和可重用性。該原則主張將不同層面的關注點獨立開發,使得修改一個關注點不會影響其他關注點。
- 傳統的網頁開發中,通常會將網頁的開發區分為 HTML、CSS、JavaScript 三個技術領域,並分別將它們拆分成不同的檔案,以負責各自的領域。
- HTML: 語意層,負責網頁結構和整體語意。
- CSS: 樣式層,負責網頁外觀和樣式。
- JavaScript: 邏輯層,負責處理事件邏輯和動態行為。
- 避免寫行內樣式(inline style)跟行內腳本(inline script)造成彼此領域的干涉。
<h1 style="color:red;font-size:46px;" onclick="alert('Hi')">
Hello World
</h1>
- 關注點分離寫法
- HTML(語意層):
<h1>
Hello World
</h1>
- CSS(樣式層)
h1 {
color: red;
font-size: 46px;
}
- 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 進行彼此的溝通而不直接互相影響。
- 透過以下流程搭配程式碼進行說明
- 用戶與界面互動,觸發 Controller 的相應方法。
- 使用者在瀏覽器點擊移除。
- Controller 根據用戶的輸入操作 Model。
- 按鈕的點擊事件觸發了 removeData 方法,這是 Controller 中的一個相應方法。
- Model 的狀態發生變化。
- removeData 方法中使用了 splice 方法來移除資料陣列 data 中的特定項目,即刪除了一個資料項。
- Controller 得知 Model 狀態的變化,通知相應的 View。
- removeData 方法執行完畢後,立即呼叫了 render 方法,這是通知 View 部分。
- View 從 Model 中獲取最新的數據。
- render 方法內部重新遍歷資料陣列,創建新的 HTML 元素,並更新 DOM 中的內容。
- View 使用這些數據更新界面。
- 新的 HTML 元素被注入到 DOM 中,此時界面上的列表已經更新,反映了資料變化。
- 用戶與界面互動,觸發 Controller 的相應方法。
程式碼:
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。