JS Modularity 過程筆記 - 汰換大型專案中所有 alert 成全域可用的訊息區塊

Posted by Young on 2023-06-28
Estimated Reading Time 5 Minutes
Words 1.4k In Total
Viewed Times

為何現今網站逐漸避免使用 alert()?

基本上只要超過 10 年的專案都會時常看到運用大量的 alert() 來處理後端回傳的訊息,但現今網站大多逐漸避免使用 alert(),主要原因有以下幾點:

  • 中斷用戶體驗:當 alert() 彈出時,它會阻擋用戶與網頁的其他部分進行互動,直到用戶關閉 alert()。往往會打斷用戶的操作流程,特別是當 alert() 用於顯示非關鍵性資訊時就顯得更不必要
  • 樣式與設計限制:alert() 的外觀和設計通常是由瀏覽器決定的,而非開發人員。這使得 alert() 很難與網站的品牌和設計風格保持一致。且 alert() 缺乏自定義的選項,如動畫、圖標和布局
  • 缺乏靈活性: alert() 只能顯示簡單的文字訊息,並且不能包含複雜的元素或交互。此外, alert() 無法控制顯示的位置,總是會在畫面中央彈出。

設計一個訊息 JS 模組

一開始由於只是再修改一個特定的 Dashboard 頁面,只想試試能不能取代到以往那煩人的 alert(),所以先直接將 appendMessage() 函數跟與這個頁面相關的 js 寫在一起。

如下所示:

1
2
<!-- js 回傳顯示對應訊息的區塊 -->
<div id="messages"></div>

直接跟此頁面的其他 JS 函數參雜在一起

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function validmobileauthcode(mobile, authcode) {
..............
$.ajax({
......................
success: function (rt) {
if (rt["code"] == 0) {
appendMessage(rt["msg"], false);
} else {
appendMessage(rt["msg"], true);
}
},
});
}
// 顯示訊息
function appendMessage(message, isSuccess) {
var messageDiv = document.createElement("div");
// 使用 Tailwind CSS 样式化消息
var classes = "m-4 p-4 rounded border font-bold ";
classes += isSuccess
? "bg-green-100 border-green-400 text-green-700"
: "bg-red-100 border-red-400 text-red-700";

messageDiv.className = classes;
messageDiv.textContent = message;

var container = document.getElementById("messages");
// 覆蓋原本的訊息,避免訊息一次顯示多個
container.innerHTML = "";
container.appendChild(messageDiv);
}

後來發現效果非常好,開始決定計畫將整個專案的 alert() 全部換成這種訊息模塊的方式來呈現。

Design Pattern

很多初學者或是趕下班的工程師,當遇到需要在多個頁面使用訊息模塊時,往往會直接將 appendMessage() 函數複製貼上到相關頁面的 js 文件中。然而,這樣的作法具有幾個明顯的缺點:

  • 可維護性低
  • 程式碼重複性高
  • 不具彈性:當你想要對訊息的顯示進行不同的客製化,會開始恨之前使用在每個 js 複製貼上的自己,因為你必須在每個地方都修改程式碼。

身為工程師就應該思考如何用最「精簡」的程式碼來達到目的。而不是直接當起人體打印機

將顯示訊息功能模組化

為了確保在每一個頁面都能使用到此訊息模組,我們可以將此程式抽離出來,並將其封裝成一個獨立的 JS 模組。

先建立一個名為 appendMessage.js 的檔案,並有個好習慣,先為此函數加上註解,讓後續其他工程師在使用時能夠快速了解此函數的用途。

1
2
3
4
5
6
7
8
// appendMessage.js
/**
* 顯示訊息
* @param {string} message - 消息內容
* @param {boolean} isSuccess - 是否顯示為成功消息
* @param {string} containerId - 消息應顯示在哪個元素
* @param {number} displayTime - 消息顯示的時間(毫秒),如果是0則不會自動消失
*/

功能實作

將程式模組化後,還額外新增了一個可以讓訊息區塊自動消失的功能,並且可自訂顯示的時間。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// appendMessage.js
function showMessage(message,isSuccess,containerId = "messages",displayTime = 3000) {
var messageDiv = document.createElement("div");
// 使用 Tailwind CSS 样式化消息
var classes = "m-4 p-4 rounded border font-bold ";
classes += isSuccess
? "bg-green-100 border-green-400 text-green-700"
: "bg-red-100 border-red-400 text-red-700";

messageDiv.className = classes;
messageDiv.textContent = message;

// 找到要顯示消息的容器,並清空現有內容
var container = document.getElementById(containerId);
container.innerHTML = "";
container.appendChild(messageDiv);

// 如果displayTime大於0,則設置一個定時器來自動移除消息
if (displayTime > 0) {
setTimeout(function () {
container.removeChild(messageDiv);
}, displayTime);
}
}

嵌入至專案 Header

將寫好的 JS 模組嵌入至專案中。

1
2
<!-- 顯示訊息區塊的 JS -->
<script src="/js/appendMessage.js?v=<?php echo $version; ?>"></script>

並將產生訊息的 <div> 區塊擺放專案中所有頁面都能看到的 Header 中。

1
2
<!-- js 回傳顯示對應訊息的區塊 -->
<div id="messages"></div>

自制訊息模組

往後在專案就可以只用單單一行並代入參數就可以直接使用完全客製化的訊息模組。

這邊不給使用預設的顯示 3 秒,若不想自動消失,也可以在參數中帶入 0 給 displayTime 即可。

1
2
3
4
if (condition) { // 密碼重置成功
showMessage(check,true);
// showMessage("測弒訊息。", false, "errorContainer", 0);
}

未來想修改訊息區塊的樣式也只需要去 appendMessage.js 修改一次即可,不用再去每個頁面都修改一次。

1
2
3
4
5
// 使用 Tailwind CSS 樣式化消息
var classes = "m-4 p-4 rounded border font-bold ";
classes += isSuccess
? "bg-green-100 border-green-400 text-green-700"
: "bg-red-100 border-red-400 text-red-700";

message-block


若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~


留言版