從一個頁面開關講講有限狀態機

故事起源於最近看一位朋友在實現一個 播放/暫停 按鈕時, 一些思路上的碰撞,
因而整理出本文, 講解一下如何用 有限狀態機 使代碼更簡潔可靠.

咱們想實現上面這樣的按鈕交互, 先看看原版實現: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

相關文章
相關標籤/搜索