React文檔(十九)不使用ES6

一般你會將一個React組件定義成一個普通的js類:react

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

若是你不打算使用ES6,你也可使用create-react-class 模塊:app

var createReactClass = require('create-react-class'); var Greeting = createReactClass({ render: function() { return <h1>Hello, {this.props.name}</h1>; } });
ES6 中 class 相關的接口與 createReactClass 方法十分類似,但有如下幾個區別值得注意。

聲明defaultProps函數

若是使用 class 關鍵字建立組件,能夠直接把自定義屬性對象寫到類的 defaultProps 屬性中:
class Greeting extends React.Component {
  // ...
}

Greeting.defaultProps = {
  name: 'Mary'
};
若是使用 createReactClass 方法建立組件,那就須要在參數對象中定義 getDefaultProps 方法,而且在這個方法中返回包含自定義屬性的對象:
var Greeting = createReactClass({ getDefaultProps: function() { return { name: 'Mary' }; }, // ... });

設置初始state性能

在ES6類中,你能夠在構造函數中經過this.state定義初始state:ui

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  // ...
}
若是使用 createReactClass 方法建立組件,你就須要多寫一個 getInitialState 方法,並讓這個方法返回你要定義的初始屬性:
var Counter = createReactClass({ getInitialState: function() { return {count: this.props.initialCount}; }, // ... });

自動綁定this

對於使用 class 關鍵字建立的 React 組件,組件中的方法是不會自動綁定 this 的。相似地,經過 ES6 class 生成的實例,實例上的方法也不會綁定 this。所以,你須要在 constructor 中爲方法手動添加 .bind(this):
class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'Hello!'};
    // This line is important!
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    alert(this.state.message);
  }

  render() {
    // Because `this.handleClick` is bound, we can use it as an event handler.
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
}
若是使用 createReactClass 方法建立組件,組件中的方法會自動綁定至實例,不須要像上面那樣加 .bind(this):
var SayHello = createReactClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },

  handleClick: function() {
    alert(this.state.message);
  },

  render: function() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
});

這就意味着若是使用ES6類的語法將會爲了事件處理器寫更多的代碼,可是優點就是在大型應用中性能稍微好一點。spa

若是你以爲上面這個寫法很麻煩,那麼能夠嘗試一下目前還處於實驗性階段的 Babel 插件 Class Properties。
class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'Hello!'};
  }
  // WARNING: this syntax is experimental!
  // Using an arrow here binds the method:
  handleClick = () => {
    alert(this.state.message);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
}
請注意,這種語法目前還處於實驗性階段。也就意味着,語法隨時均可能改變。固然,也存在最終沒有被官方批准的可能。

爲了保險起見,如下三種作法都是能夠的:插件

  • 在構造函數中綁定方法
  • 使用箭頭函數,例如onClick={(e) => this.handleClick(e)}
  • 使用React.createClass()

mixins(混入)code

注意:component

ES6 自己是不包含混入支持的。所以,若是你使用 class 關鍵字建立組件,那就不能使用混入功能了。

咱們也發現了不少使用混入而後出現了問題的代碼庫。所以,咱們並不推薦在 ES6 中使用混入.

如下內容僅做爲參考

有些時候那些不一樣的組件也許會分享一些相同的功能。它們有時被叫作橫切關注點。針對這個問題,在使用 createReactClass 建立 React 組件的時候,引入混入功能會是一個很好的解決方案。

一個常見的使用場景就是一個組件想要經過一個interval定時器來更新本身。使用setInterval()會很方便,可是在你不須要的時候你要關閉定時器來節省內存。React提供了生命週期方法讓你知道何時組件被建立和被銷燬。讓咱們建立一個簡單的mixins使用這些方法來提供一個簡單的setInterval()函數來自動清除定時器當你的組件被銷燬。

var SetIntervalMixin = {
  componentWillMount: function() {
    this.intervals = [];
  },
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
    this.intervals.forEach(clearInterval);
  }
};

var createReactClass = require('create-react-class');

var TickTock = createReactClass({
  mixins: [SetIntervalMixin], // 使用混入
  getInitialState: function() {
    return {seconds: 0};
  },
  componentDidMount: function() {
    this.setInterval(this.tick, 1000); // 調用混入的方法
  },
  tick: function() {
    this.setState({seconds: this.state.seconds + 1});
  },
  render: function() {
    return (
      <p>
        React has been running for {this.state.seconds} seconds.
      </p>
    );
  }
});

ReactDOM.render(
  <TickTock />,
  document.getElementById('example')
);

若是一個組件有多個混入,且其中幾個混入中定義了相同的生命週期方法(好比都會在組件被摧毀的時候執行),那麼這些生命週期方法是必定會被調用的。經過混入定義的方法,執行順序也與定義時的順序一致,且會在組件上的方法執行以後再執行。

相關文章
相關標籤/搜索