故事起源於最近看一位朋友在實現一個 播放/暫停 按鈕時, 一些思路上的碰撞,
因而整理出本文, 講解一下如何用 有限狀態機 使代碼更簡潔可靠.
咱們想實現上面這樣的按鈕交互, 先看看原版實現:app
$('#botton').on('click', function(){ if ( $(this).text() === 'OFF' ){ //把按鈕的文案改變一下 $(this).text('ON'); //開始播放 $('#player').start(); } else { $(this).text('OFF'); $('#player').stop(); } });
這是一個基本的實現方式, 也是一個最簡單的方式.函數
不過,this
按照這個方式來作有幾個不太優雅的地方:編碼
if / else
裏面的代碼愈來愈臃腫.on/off
兩種, 咱們可能須要些一堆 else if
或者用switch / case
先看代碼:spa
var fsm = (function(){ //初始狀態 var status = 1; //狀態對應的操做 var mapping = { '1': { text:'ON', action: $('#player').start }, '-1': { text:'OFF', action: $('#player').stop }, }; return function(btn){ //經過 *-1 實現status從 1/-1 切換 status *= -1; btn.text( mapping[status].text ); var fn = mapping[status].action; fn(); } })(); $('#botton').click(function(){ fsm(this); });
閱讀上面代碼能發現, 對botton
的點擊事件處理, 只須要調用fsm
函數便可, 內部的變化和操做, 都不須要暴露出來.code
fsm
內部, 經過mapping
來定義和限制行爲, 惟一可以改變的只有status
,事件
這樣的好處在於, 可以避免在編碼過程當中人爲的錯誤, 由於事件響應部分只能有限的操做狀態機的status
,而不是直接參與botton
的行爲與表現.rem
同時, 功能的擴展, 狀態的增減, 都只須要在mapping
裏面定義好, 很是利於擴展與維護.it