實現一個簡單的 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個技巧