用ES6書寫React

weixin_34007291發表於2016-11-03

前段時間學習react+redux的時候發現現在大家基本上都是在用es6的方式編寫react程式碼。由於習慣了react本身的編寫方式,起初看得雲裡霧裡。當自己實踐過後發現es6+react確實能夠讓程式碼更加簡潔,提高開發效率。

起步

首先需要安裝react

npm install react react-dom --save-dev

使用es6(7)需要babel轉換器,本人使用的是webpack自動化工具

npm install webpack --save-dev
npm install babel-preset-es2015 --save-dev //轉換至es5
npm install babel-preset-react --save-dev //轉換jsx至es5
npm install babel-preset-stage-2 --save-dev //支援es7
npm install babel-loader --save-dev //webpack的babel載入器

配置webpack

//webpack.config.js
module.exports={
    entry:"./main.js",
    output:{
        path:__dirname,
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.js$/,
            exclude:/node_modules/,
            loader:"babel-loader",
            query:{
                presets:["es2015","stage-2","react"]
            }
        }]
    }
}

現在準備工作做好了,接下來的任務就是用新的方式編寫入口檔案。(main.js)

ES6-React

載入模組

通過引入react.js和react-dom.js我們可以直接使用React和ReactDOM這兩個物件,這是傳統的方式

//html中需要先引入react.js和react-dom.js
console.log(React);
console.log(ReactDOM);

現在我們使用es6的方式

//不需要提前引入任何檔案
import React from "react";
import ReactDOM from "react-dom";
console.log(React);
console.log(ReactDOM);

建立元件

使用類來建立元件代替React.createClass

import React from "react";
class MyComponent extends React.Component{
//元件內部程式碼
}

你也可以用另一種方式

import React,{Component} from "react";
class MyComponent extends Component{
//元件內部程式碼
}

State/Props/PropTypes

//傳統的react
var MyComponent=React.createClass({
  getDefaultProps:function(){
    return {
      name:"SunnyChuan",
      age:22
    };
  },
  propTypes:{
    name:React.PropTypes.string.isRequired,
    age:React.PropTypes.number.isRequired
  }
});

es6允許將props和propTypes當作靜態屬性在類外初始化

class MyComponent extends React.Component{}
MyComponent.defaultProps={
  name:"SunnyChuan",
  age:22
};
MyComponent.propTypes={
  name:React.PropTypes.string.isRequired,
  age:React.PropTypes.number.isRequired
};

es7支援直接在類中使用變數表示式,這也是我推薦的寫法

class MyComponent extends React.Component{
  static defaultProps={
    name:"SunnyChuan",
    age:22
  }
  static propTypes={
    name:React.PropTypes.string.isRequired,
    age:React.PropTypes.number.isRequired
  }
}

state和前兩個不同,它不是靜態的

class MyComponent extends React.Component{
  static defaultProps={
    name:"SunnyChuan",
    age:22
  }
  state={
     isMarried:false
  }
  static propTypes={
    name:React.PropTypes.string.isRequired,
    age:React.PropTypes.number.isRequired
  }
}

函式

React.createClass本身接收的是一個物件,對於物件中的方法,es6允許使用key(){}的形式取代key:function(){}

class MyComponent extends React.Component{
  state={
    count:0
  }
  handleChange(){
    this.setState({count:this.state.count+1});
  }
}

需要注意的是,由於使用class建立元件,react不會再自動幫我們繫結作用域了,我們需要自己手動解決

class MyComponent extends React.Component{
  state={
    count:0
  }
  handleChange(){
    this.setState({count:this.state.count+1});
  }
  render(){
    return (
      <div>
        <h2>當前計數是:{this.state.count}</h2>
        <button onClick={this.handleChange.bind(this)}>點選</button>
      </div>
    )
  }
}

如果你覺得這種每次都需要繫結的方法太麻煩,也可以在建構函式中去繫結

class MyComponent extends React.Component{
  constructor(props){
    super(props);
    this.handleChange=this.handleChange.bind(this);
  }
  state={
    count:0
  }
  handleChange(){
    this.setState({count:this.state.count+1});
  }
  render(){
    return (
      <div>
        <h2>當前計數是:{this.state.count}</h2>
        <button onClick={this.handleChange}>點選</button>
      </div>
    )
  }
}

如果你覺得這種方式也麻煩,可以使用es6的箭頭函式(自動繫結作用域),但是前提是你的環境要支援es7,因為箭頭函式相當於表示式宣告函式的簡寫,只有es7支援在類中這麼使用(類中使用表示式state/props/propTypes也只有es7支援)

class MyComponent extends React.Component{
  state={
    count:0
  }
  handleChange=()=>{
    this.setState({count:this.state.count+1});
  }
  render(){
    return (
      <div>
        <h2>當前計數是:{this.state.count}</h2>
        <button onClick={this.handleChange}>點選</button>
      </div>
    )
  }
}

元件生命週期

所有的元件生命週期都可以當作普通函式使用上述三種方式編寫,componentWillMount比較特殊,它還可以在建構函式中編寫

class MyComponent extends React.Component{
  componentWillMount(){
    console.log("Hello SunnyChuan");
  }
}
//二者等價
class MyComponent extends React.Component{
  constructor(props){
    console.log("Hello SunnyChuan")
  }
}

擴充套件操作符

使用react開發最常見的問題就是父元件要傳給子元件的屬性較多時比較麻煩

class MyComponent extends React.Component{
//假設MyComponent已經有了name和age屬性
  render(){
    return (
      <SubComponent name={this.props.name} age={this.props.age}/>
     )
  }
}

使用擴充套件操作符可以變得很簡單

class MyComponent extends React.Component{
//假設MyComponent已經有了name和age屬性
  render(){
    return (
      <SubComponent {...this.props}/>
     )
  }
}

上述方式是將父元件的所有屬性都傳遞下去,如果這其中有些屬性我不需要傳遞呢?也很簡單

class MyComponent extends React.Component{
//假設MyComponent有很多屬性,而name屬性不需要傳遞給子元件
  var {name,...MyProps}=this.props;
  render(){
    return (
      <SubComponent {...Myprops}/>
     )
  }
}

上述方法最常用的場景就是父元件的class屬性需要被單獨提取出來作為某個元素的class,而其他屬性需要傳遞給子元件。

模組化開發元件

說了這麼多,個人認為es6+react最吸引人的地方就是模組化開發,將每個小(大)元件當作一個模組

//father.js
import React from "react";
import ReactDOM from "react-dom";
import {SonComponent} from "son.js";
class FatherComponent extends React.Component{ 
  //省去中間的業務邏輯
  render(){
    return (<SonComponent/>);
  }
}
ReactDOM.render(<FatherComponent/>,document.getElementById("ss"));
//son.js
import React from "react";
class SonComponent extends React.Component{
  //省去中間的業務邏輯
  render(){
    return (<h2>"SunnyChuan"</h2>);
  }
}
export {SonComponent};

如果你把子元件的匯出設定為default export,那麼在匯入時就不必再加{}

//father.js
import SonComponent from "son.js";
//son.js
export default class SonComponent extends React.Component{
  //省去中間的業務邏輯
}

花一點時間學習es6(7)+react的開發方式,你會更加喜歡使用react。

相關文章