實現一個簡單的 JavaScript 狀態機[每日前端夜話0xBF]
- 2019 年 10 月 4 日
- 筆記
每日前端夜話0xBE
每日前端夜話,陪你聊前端。
每天晚上18:00準時推送。
正文共:850 字
預計閱讀時間:7 分鐘
作者:Nalla Senthilnathan
翻譯:瘋狂的技術宅
來源:dzone
使用簡單的狀態機創建乾淨且健壯的 UI
使用狀態機可以構建健壯的 UI,其好處已有詳細的描述—— 例如你可以參見Edward J. Pring 的文章和 David Khourshid 的影片。另外Krasimir Tsonev 描述了 JavaScript 中狀態機的一些常用方法。一些比較流行的 JavaScript 庫是 jakesgordon/javascript-state-machine 和 davidkpiano/xstate 。
在本文中,我將實現一個用於 JavaScript UI 的簡單的狀態機。為了保持內容簡潔,我使用了 jQuery。
經典十字旋轉門問題
狀態機的經典 「Hello,World」 示例是 Turnstile。以下步驟描述了怎樣把狀態機應用於十字旋轉門問題:
步驟1:編寫狀態轉換表如:
defaultState |
coinEvent |
handleCoin() |
coinSuccessEvent |
coinSuccessState |
---|---|---|---|---|
defaultState |
coinEvent |
handleCoin() |
coinErrorEvent |
coinErrorState |
coinErrorState |
coinEvent |
handleCoin() |
coinSuccessEvent |
coinSuccessState |
coinSuccessState |
pushEvent |
pushHandler() |
pushSuccessEvent |
pushEventState |
步驟2:捕獲數據結構中的狀態:
const turnstileStates = { defaultState : function() { $("#thankyou").hide(); $("#cointxt").val(""); $("#push").prop("disabled", true); $("#cointxt").prop("disabled", false); $("#turnstile_locked").show(); $("#turnstile_unlocked").hide(); $("#coinerrmsg").hide(); }, coinSuccessState : function() { $("#turnstile_locked").hide(); $("#cointxt").prop("disabled", true); $("#push").prop("disabled", false); $("#coin").prop("disabled", true); $("#turnstile_unlocked").show(); $("#coinerrmsg").hide(); }, coinErrorState : function() { $("#thankyou").hide(); $("#cointxt").prop("disabled", false); $("#push").prop("disabled", true); $("#turnstile_locked").show(); $("#coinerrmsg").show(); $("#turnstile_unlocked").hide(); }, pushSuccessState : function() { $("#thankyou").show(); $("#welcome").hide(); $("#cointxt").prop("disabled", true); $("#turnstile_locked").hide(); $("#coin").prop("disabled", true); $("#push").prop("disabled", true); $("#turnstile_unlocked").hide(); $("#coinerrmsg").hide(); } };
注意,可以通過重構上面的函數體,來使用適當的數據參數調用類似 renderComponent() 的方法。我在這裡用了詳細模式,因此讀者可以在一個地方快速看到 turnstileStates 配置背後的概念。
在這個 「Hello,World」 示例中,我沒有使用來自於伺服器的任何數據(模型)。當我們從伺服器獲得這樣的模型時,turnstileStates 結構中的函數可以存在一個模型參數。
步驟3:捕獲事件和事件處理
const turnstileEvents = { coinEvent : { handleCoin : function(e) { if (e.data.coinval() > 0) { return turnstileEvents.coinSuccessEvent; } else { return turnstileEvents.coinErrorEvent; } } //nextState not needed for this event }, coinSuccessEvent : { nextState : function() { return turnstileStates.coinSuccessState(); } //no handlers are needed for this event }, coinErrorEvent : { nextState : function() { return turnstileStates.coinErrorState(); } //no handlers are needed for this event }, pushEvent : { handlePush : function() { return turnstileEvents.pushSuccessEvent; } //nextState not needed for this event }, pushSuccessEvent : { nextState : function() { return turnstileStates.pushSuccessState(); } //no handlers are needed for this event } };
注意:nextnate 屬性用於 turnstileEvents 配置而不是 turnstileStates 配置,因為我們在狀態轉換表中看到事後指示的下一個狀態應該是什麼。
步驟4:編排控制器中的狀態和事件(在我們的例子中是 jQuery body):
//handle the page load event turnstileStates.defaultState(); //handle the coin event $("#coin").on("click",{ coinval : function(){return $("#cointxt").val();} },function(event) { return turnstileEvents.coinEvent.handleCoin(event).nextState(); }); //handle the push event $("#push").click(function() { return turnstileEvents.pushEvent.handlePush().nextState(); });
你可以查看本例的在線演示(https://mapteb.github.io/js-state-machine/jqueryStateMachineDemo.html),其中可以測試四個狀態轉換。該演示的完整源程式碼可在 GitHub 上找到。
結論
值得注意的是,用於 Java 程式的方法同樣適用於JavaScript 程式。這個方法的一個特別之處在於三個組件中的關注點的清晰分離 —— 狀態、事件/事件處理handler和控制器。總之,把狀態機用於前端應用能夠有助於構建乾淨且健壯的 UI。 原文:https://dzone.com/articles/a-simple-javascript-state-machine
下面夾雜一些私貨:也許你和高薪之間只差這一張圖
2019年京程一燈課程體系上新,這是我們第一次將全部課程列表對外開放。
願你有個好前程,願你月薪30K。我們是認真的 !
往期精選
- BootstrapVue 入門
- JavaScript的工作原理:引擎、運行時和調用堆棧
- 用 TypeScript 開發 Node.js 程式
- 快速上手最新的 Vue CLI 3
- JavaScript 程式設計師可以從C ++中學到些什麼
- 在同一基準下對前端框架進行比較
- Edge 擁抱 Chromium 對前端工程師意味著什麼?
- 使你的 JavaScript 程式碼簡單易讀
- Node.js多執行緒完全指南
- deno如何償還Node.js的十大技術債
- 實戰!半小時寫一個腦力小遊戲
- CSS Flexbox 可視化手冊
- 世界頂級公司的前端面試都問些什麼
- V8引擎內部機制及優化程式碼的5個技巧