故事起源于最近看一位朋友在实现一个 播放/暂停 按钮时, 一些思路上的碰撞,
因而整理出本文, 讲解一下如何用 有限状态机 使代码更简洁可靠.
咱们想实现上面这样的按钮交互, 先看看原版实现: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