前端之React實戰-交互與動態UI

Interactivity and Dynamic UIs

React.findDOMNode()

組件並非真實的 DOM 節點,而是存在於內存之中的一種數據結構,叫作虛擬 DOM (virtual DOM)。只有當它插入文檔之後,纔會變成真實的 DOM 。根據 React 的設計,全部的 DOM 變更,都先在虛擬 DOM上發生,而後再將實際發生變更的部分,反映在真實 DOM上,這種算法叫作 DOM diff ,它能夠極大提升網頁的性能表現。可是,有時須要從組件獲取真實 DOM 的節點,這時就要用到 React.findDOMNode 方法。javascript

var MyComponent = React.createClass({
  handleClick: function() {
    React.findDOMNode(this.refs.myTextInput).focus();
  },
  render: function() {
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input type="button" value="Focus the text input" onClick={this.handleClick} />
      </div>
    );
  }
});

React.render(
  <MyComponent />,
  document.getElementById('example')
);

須要注意的是,因爲 React.findDOMNode 方法獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個方法,不然會返回 null 。上面代碼中,經過爲組件指定 Click 事件的回調函數,確保了只有等到真實 DOM 發生 Click 事件以後,纔會調用 React.findDOMNode 方法。css

getInitialState

設置State的初始狀態。html

var MyComponent = React.createClass({
    getInitialState: function(){
        return {
            count: 5
        }
    },
    render: function(){
        return (
            <h1>{this.state.count}</h1>
        )
    }
});

Style

參考資料java

  • React行內樣式最佳實踐react

Inline-style

在React中,若是要使用行內元素,不能夠直接使用style="」這種方式,能夠有:git

import React from 'react';

var style = {
  backgroundColor: '#EEE'
};

export default React.createClass({
  render: function () {
    return (
      <div style={style}>
      //或者<div style={{backgroundColor: '#EEE'}}>
        <h1>Hello world</h1>
      </div>
    )
  }
});

能夠看出,React的style屬性接收的也是一個JavaScript對象。github

Class

你能夠根據這個策略爲每一個組件建立 CSS 文件,可讓組件名和 CSS 中的 class 使用一個命名空間,來避免一個組件中的一些 class 干擾到另一些組件的 class。算法

app/components/MyComponent.cssapi

.MyComponent-wrapper {
  background-color: #EEE;
}

app/components/MyComponent.jsx瀏覽器

import './MyComponent.css';
import React from 'react';

export default React.createClass({
  render: function () {
    return (
      <div className="MyComponent-wrapper">
        <h1>Hello world</h1>
      </div>
    )
  }
});

Multiple Class

上文中說起的利用className方式賦值,若是在存在多個類名的狀況下:

render: function() {
  var cx = React.addons.classSet;
  var classes = cx({
    'message': true,
    'message-important': this.props.isImportant,
    'message-read': this.props.isRead
  });
  // same final string, but much cleaner
  return <div className={classes}>Great, I'll be there.</div>;
}

Event

React對於事件的支持很是完善,能夠查看這裏。React 實現了一個「合成事件」層(synthetic event system),這個事件模型保證了和 W3C 標準保持一致,因此不用擔憂有什麼詭異的用法,而且這個事件層消除了 IE 與 W3C 標準實現之間的兼容問題。「合成事件」額外提供了兩個好處:自動綁定上下文和事件委託

  • 「合成事件」自動將事處理件方法的上下文綁到當前組件,因此 handleClick 方法裏面能夠直接使用this.setState

  • 「合成事件」會以事件委託(event delegation)的方式綁定到組件最上層,而且在組件卸載(unmount)的時候自動銷燬綁定的事件。

固然,在React中,也可使用原生事件,好比你在 componentDidMount 方法裏面經過 addEventListener 綁定的事件就是瀏覽器原生事件。使用原生事件的時候注意在 componentWillUnmount 解除綁定 removeEventListener。全部經過 JSX 這種方式綁定的事件都是綁定到「合成事件」,除非你有特別的理由,建議老是用 React 的方式處理事件。

Event Bind

最基本的綁定方式就是依靠相似於onClick={handleClick}的方式,要注意,這裏不一樣於ng-click,onClick傳遞的參數只能是一個方法,而不能是一個調用。若是要簡單來寫的話能夠採Lambda表達式的方式:

onClick={()=>{alert(1);}}

Event Params

給事件處理函數傳遞額外參數的方式:bind(this, arg1, arg2, ...)

render: function() {
    return <p onClick={this.handleClick.bind(this, 'extra param')}>;
},
handleClick: function(param, event) {
    // handle click
}

由上面能夠看出,Event通常都是做爲最後一個參數傳遞到handleClick中,這裏的event是SyntheticEvent對象,它的主要屬性以下:

boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
void preventDefault()
void isDefaultPrevented()
void stopPropagation()
void isPropagationStopped()
DOMEventTarget target
number timeStamp
string type

List Element

在React中,也會常常遇到須要爲某個羣組綁定事件的狀況,能夠參考以下代碼:

var GroceryList = React.createClass({
  handleClick: function(i) {
    console.log('You clicked: ' + this.props.items[i]);
  },
  render: function() {
    return (
      <div>
        {this.props.items.map(function(item, i) {
          return (
            <div onClick={this.handleClick.bind(this, i)} key={i}>{item}</div>
          );
        }, this)}
      </div>
    );
  }
});
React.render(
  <GroceryList items={['Apple', 'Banana', 'Cranberry']} />, mountNode
);

TouchEvent

If you'd like to use React on a touch device such as a phone or tablet, simply call React.initializeTouchEvents(true); to enable touch event handling.

接口暴露

譬如在某個子組件中,提供了某個方法:

var ButtonComponent = React.createClass({
    getDragonKillingSword: function(){
        //送寶刀
    },
    render: function(){
        return (<button onClick={this.getDragonKillingSword}>屠龍寶刀,點擊就送</button>);
    }
});

若是在父組件中想手動調用該方法,則能夠利用ref方式:

var ImDaddyComponent = React.createClass({
  render: function(){
    return (
      <div>
        //其餘組件
        <ButtonComponent />
        //其餘組件
      </div>
    );
  }
});

在父組件的功能方程中:

this.refs.getSwordButton.getDragonKillingSword();

反之,若是須要在子組件中調用父組件的方法,則能夠直接將父組件的方法做爲Props參數傳入到子組件中:

<ButtonComponent clickCallback={this.getSwordButtonClickCallback}/>

Ajax

組件的數據來源,一般是經過 Ajax 請求從服務器獲取,能夠在componentDidMount 方法中設置 Ajax 請求,等到請求成功,再用 this.setState 方法從新渲染 UI。

var UserGist = React.createClass({
      getInitialState: function() {
        return {
          username: '',
          lastGistUrl: ''
        };
      },

      componentDidMount: function() {
        $.get(this.props.source, function(result) {
          var lastGist = result[0];
          if (this.isMounted()) {
            this.setState({
              username: lastGist.owner.login,
              lastGistUrl: lastGist.html_url
            });
          }
        }.bind(this));
      },

      render: function() {
        return (
          <div>
            {this.state.username}'s last gist is
            <a href={this.state.lastGistUrl}>here</a>.
          </div>
        );
      }
    });

    React.render(
      <UserGist source="https://api.github.com/users/octocat/gists" />,
      document.body
    );

不過筆者習慣仍是將整個獲取數據,處理數據的業務邏輯放在Angular中進行。

相關文章
相關標籤/搜索