Thinking In React Way - 有限狀態機

今天來聊聊前端,其實這個專題剛開始寫起來的時候,是想和你們分享數據可視化的一些知識的。這也是圖表君名頭的由來,後來慢慢就寫進了些前端的東西,再後來,由於圖表君工做的轉換,如今更多的作一些後臺的工做,那麼討論的問題就更雜了,如今看起來算是個人一些工做和學習心得和感覺吧。javascript

好了,說了這麼多。今天聊點什麼呢?聊聊React。其實這也並非什麼新東西了。2014年,圖表君就知道有這麼個東西,聽着幾位業界大牛聊,說這東西有多麼多麼的好,當時也不是特別的理解,跟了一遍官方的Tutorial,也沒有特別的感覺。應該是由於當時前端的經驗特別的淺(雖然如今也不敢說深,捂臉),沒有什麼特別的感覺吧。html

Angular的痛

後來作了幾個項目,使用的是Angular,剛開始以爲雙向數據綁定好牛逼啊,好好用,好好用。可是隨着項目逐漸的一點點變大,感受$scope上的東西是愈來愈多,各個controller裏各有各的$scope,再加上$scope是繼承的,當項目一複雜就愈來愈難以管理和控制。還有本身要封裝一個組件在angular裏得用directive吧,好吧看看directive的文檔你就得暈了,link,compile,controller都是什麼鬼。好了,今天不是吐槽angular的時間,可是angular得設計和使用的確是太複雜了。前端

前端究竟是在幹什麼

好了,讓咱們先暫時跳出框架的討論,來思考一下,前端的工做究竟是幹什麼的?其實能夠簡單的說就是將數據到View的一個映射上,也就是說不管什麼框架解決的基本問題就是講數據展現到View上, 而後將講用戶的操做最後再反應到數據的變化上來。java

Data --> Whatever FrameWork --> View
                    Data <-- Whatever FrameWork <-- View

再想清楚這個問題以後,React是怎麼作的呢?React並非一個完整的前端框架,只是一個專一於渲染View的library,在看了React的文檔以後,咱們會發現他的api是很簡單的。一個典型的react的組件react

class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// Example usage: <ShoppingList name="Mark" />

即便你沒有React的經驗,看這樣的代碼也不會有什麼特別的問題。好了,今天圖表君不打算安利React,並不想寫一個hello world出來。這樣的文章太多,看看React的官方例子會比圖表君寫的好不少。那麼今天說什麼呢?git

React Thinking - 狀態機

看這部分以前,圖表君強烈建議你能夠看一看React的官方tutorialtutorial,很好的一個例子,也不長。一個小時就能看完,本身上手寫一寫,感覺會更深。好了如今假設你看完了這個tutorial有什麼感受?github

圖表君的最大的感覺是,最後將State,function都定義到了Game的這個Root級別的Component上了,再把全部的數據和function都傳進本身的子Component裏,須要的地方直接調用就行了。這樣就使得咱們上邊說把Data的操做邏輯都被提出來,並集中在一塊兒了,一下就清晰了,明確了。App管理今後變得一下簡單了。反覆品味這樣的設計,突然有個東西,進入了個人思惟裏。這東西不就是一個有限狀態機呀。api

有限狀態機

FSM

有限狀態機是個十分有用的模型,能夠用來模擬世界上大部分的事物,其有三個特徵:前端框架

  1. 狀態總數(state)是有限的。框架

  2. 任一時刻,只處在一種狀態之中。

  3. 某種條件下,會從一種狀態轉變(transition)到另外一種狀態。

咱們再來看看例子中的代碼

class Game extends React.Component {
  constructor(){
    super();
    this.state={
      history:[{
        squares: Array(9).fill(null)
      }],
      stepNumber: 0,
      xIsNext: true
    }
  }
  
  handleClick(i){
    const history = this.state.history;
    const stepNumber = this.state.stepNumber
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext? 'X':'O';
    this.setState(
      {
        history: history.concat([{
      squares: squares   
    }]),
        stepNumber: stepNumber + 1,
    xIsNext: !this.state.xIsNext,
      }
    )
  }
  
  jumpTo(step){
    const newHistory = this.state.history.slice(0,step+1)
    console.log(newHistory);
    this.setState({
      history: newHistory,
      stepNumber:step,
      xIsNext: (step % 2) ? false: true, 
    })
  }
  
  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);
    let status;
    if(winner){
       status = 'Winner Is :' + winner;
    }else{
       status = 'Next player: ' + (this.state.xIsNext ? 'X':'O');
    }
    const moves = history.map((step,move) => {
       const desc = move ? 'Move #' + move : 'Game Start';
       return(
         <li key={move}>
            <a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
         </li> 
       )
    });
    return (
      <div className="game">
        <div className="game-board">
          <Board squares={current.squares} onClick={(i) => this.handleClick(i)} />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }
}

構造方法,constructor - 定義了APP的初始狀態。

handleClick - 定義了在棋盤裏點擊事件後的APP狀態的變化。

jumpTo - 定義點擊歷史記錄中某一步後APP的狀態變化。

render- 描述如何在View上來展現當前的狀態。

這樣精巧的設計,facebook果真彙集了當今世界一流的工程師。而後我看了阮一峯的這篇介紹有限狀態機的文章,看到這段代碼。

var menu = {
      
    // 當前狀態
    currentState: 'hide',
  
    // 綁定事件
    initialize: function() {
      var self = this;
      self.on("hover", self.transition);
    },
  
    // 狀態轉換
    transition: function(event){
      switch(this.currentState) {
        case "hide":
          this.currentState = 'show';
          doSomething();
          break;
        case "show":
          this.currentState = 'hide';
          doSomething();
          break;
        default:
          console.log('Invalid State!');
          break;
      }
    }
  
  };
  

有沒有似曾相識的感受,Redux裏是否是就是這麼幹的?而後再想一想Redux,到底幹了一件什麼事?幫咱們作了這樣的一個狀態機啊,咱們開發者只要定義Action,Reducer,他把咱們的APP組織成了一個狀態機。

從這樣的角度再來看React,Redux這個的技術棧,我以爲理解的更加的清楚了,固然這僅僅是個人一點點小小的思考,歡迎你們一塊兒討論拍磚,後邊逐步的和你們分享個人心得體會。

相關文章
相關標籤/搜索