React入門學習例項

w3ctech發表於2015-03-10

學習React之初並不輕鬆,不是React造了多少新概念,只是它打破了一些傳統意義上的“最佳實踐”。用React也不會令你少寫多少程式碼,什麼5分鐘寫一個blog,幾行程式碼就能實現個什麼之類的。工具不是越傻瓜越好,要看目標使用者是誰,解決什麼問題。

React是框架不是庫。區分這個的目的是不要把它當傳統認識的庫用,直接說就是不要把React當jQuery用。比如:$(‘.button’).click(doSomething),這是典型的庫思維:找到目標,轉成jQuery物件,綁上事件,執行處理。每一步都是在下“指令”。用React不要嘗試把頁面上的DOM變成虛擬DOM再do something,反過來跟jQuery混用時,也不要試圖操作React生成的DOM(這是錯誤的把React當模板引擎用了),要做什麼就通過元件例項提供的接囗do something。

先看個混用的例子,HTML:

<span class="status" data-id="1" data-status="H">無效</span>
<span class="status" data-id="2" data-status="N">有效</span>
<span class="status" data-id="3" data-status="H">無效</span>

在JS裡,做一個叫StatusModifier的元件:

$.each('.status', function(i, e){
  var el = $(e);
  var data = el.data();
  var modifier = React.render(<StatusModifier id={data.id}
                                              status={data.status}
                                              onChange={ handleChange } />, e);
  // 如果想操作元件就把modifier這個例項cache在任何方便拿的地方
  // 於是這塊互動隨它的複雜度一同被分離出去了
});

function handleChange(id, status) {
  // do something;
};

StatusModifier內部怎麼玩都可以了:

module.exports = React.createClass({
  getInitialState: function() {
    return {
      id: this.props.id,
      status: this.props.status
    }
  },
  render: function() {
    var status;
    if (this.state.status == 'H'){
      status = ['無效', 
      <a href="javascript:;" onClick={ this.handleClick.bind(this, 'N')}>啟用</a>];
    } else if (this.state.status == 'N') {
      status = ['有效',
      <a href="javascript:;" onClick={ this.handleClick.bind(this, 'H')}>暫停</a>];
    }
    return (
      <div>
      { status }
      </div>
    );
  },
  handleClick: function(status, e) {
    // 狀態變,UI自動變。
    this.replaceState({
      status: status
    });
    this.props.onChange && this.props.onChange(this.props.id, status);
  }
});

如果說這個小需求用jQuery直接寫不是更簡單嗎?當互動變了,status的情況變複雜了,這麼寫的優勢就體現出來了。比如,狀態切換是想加個動畫效果,修改一下return那裡:

...
return (
  <div>
  <FadeEffect>
  { status }
  </FadeEffect>
  </div>
);
...

FadeEffect是一個動畫效果元件。舉一個我實際專案中的例子,互動是點圖片列表中的某個圖片,預覽大圖,大圖是從小圖位置飛出:

<TweenWrapper
   className="album-preview-photo"
   from={preview.fromPos}
   to={preview.toPos}
   duration={ 300 } >
   <Image key={ preview.url } src={ preview.url } />
</TweenWrapper>

TweenWrapper是我寫的另外一個元件,參見全部程式碼。這兩個例子為了說明宣告式UI的好處。首先直觀、自然分離出元件(複雜度也自然被分離)、擴充套件靈活,個體元件即便於複用也便於測試…元件就是這樣一層層加上,也可以一層層剝去。

在React裡處理表單,參見這份完整的程式碼。以往開發中搞表單很麻煩,在React裡用狀態控制很靈活,不想重複說了。如果有問題可以po出來討論。 (@CosuScript 提到表單用DeepLinkState擴充套件會更方便高效 https://gist.github.com/NV/8622188)

相關文章