Skip to content

定义组件

不使用ES6和JSX

通常我们会使用ES6的class关键字定义组件

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

不使用ES6的class关键字定义,需要使用create-react-class模块:

var createReactClass = require('create-react-class');
var Greeting = createReactClass({
    render:function(){
        return <h1>Hello,{this.props.name}</h1>
    }
})

ES6中的class与createReactClass()方法十分相似,但是有以下几个不同需要注意:

声明默认属性

无论是函数组件还是class组件都有defaultProps属性:

class Greeting extends React.Component{}
Greeting.defaultProps = {
    name:"Mary"
}

使用create-react-class,需要定义getDefaultProps()函数:

var Greeting = createReactClass({
    getDefaultProps:function(){
        return {
            name:'Mary'
        }
    }
})

初始化state

如果使用ES6的class关键字创建组件,你可以通过给this.state赋值的方式来定义组件的初始state:

class Greeting extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            count:props.inititalCount
        }
    }
}

如果使用createReactClass的方式创建,需要提供一个单独的getInitialState方法,让其返回初始的state:

var Greeting = createReactClass({
    getInitialState:function(){
        return {count:this.props.inititalCount}
    }
})

自动绑定

对于使用ES6的class关键字创建的React组件,组件中的方法遵顼与常规class相同的语法规则。这意味这些方法不会自动绑定this到这个这个组件实例。你需要在constructor中显式地调用.bind(this):

class SayHello extends React.Component {
    constructor(props){
        super(props)
        this.handleClick = this.handleClick.bind(this)
    }
}

如果是createReactClass方法创建组件,组件中的方法会自动绑定至实例,所以不需要像上面那样做:

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 class 关键字创建组件,在处理事件回调时就要多写一部分代码。但对于大型项目来说,这样做可以提升运行效率。 为了保险起见,以下三种做法都是可以的:

  1. 在 constructor 中绑定方法。
  2. 使用箭头函数,比如:onClick={(e) => this.handleClick(e)}。
  3. 继续使用 createReactClass。

Mixins

因为ES6本身不包含任何mixin支持。因此,当你在React中使用ES6 class时,将不支持mixins。 如果完全不相同的组件有相似的功能,这就会产生"横切关注点(cross-cutting concerns)"问题。针对这个问题,使用createReactClass创建React组件的时候,引入mixins功能会时一个很好的解决方案。 比较常见的用法是,组件每个一段时间更新一次。使用setInterval()可以很容易实现这个功能,但需要注意的是,当你不再需要它的时候,你应该清楚它以节省内存。React提供了生命周期方法,这样你就可以知道一个组件何时被创建或被销毁了。让我们创建一个简单的mixin,它使用这些方法提供一个简单的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('creat-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>
            {this.state.seconds}
            <p />
        )
    }
})
ReactDOM.render(
    <TickTock / >,
    document.getElementById('example')
)

如果组件拥有多个mixins,且这些mixins中定义了相同的生命周期方法(例如,当组件被销毁时,几个mixins都想进行一些清理工作),那么这些生命周期方法都会被调用的。使用mixins时,mixins会先按照定义的顺序进行执行,最后调用组件上对于的方法。

不使用JSX的React

React并不强制要求使用JSX。当你不想在构建环境中配置有关JSX编译时,不在React中使用JSX会更加方便。 每个JSX元素只是调用React.createElement(component,props,...children)的语法糖。因此,使用JSX可以完成的任何事情都可以通过纯JavaScript完成。

例如,用JSX编写的代码:

class Hello extends React.Component{
    render(){
        return <div>Hello {this.props.name}</div>
    }
}
ReactDOM.render(
    <Hello name="world" />,
    document.querySelector('#root')
)

可以编写为不使用JSX的代码:

class Hello extends React.Component{
    render {
        return React.createElement('div',null,`hello ${this.props.name}`)
    }
}
ReactDOM.render(
    React.createElement(Hello , {name:"world"},null),
    document.querySelector('#root')
)

组件可以是字符串,也可以是React.Component的子类,它还可能是一个普通的函数。 如果你不想都键入React.createElement,通常的做法是创建快捷方式:

const e = React.createElement();
ReactDOM.render(
    e('div',null,'hello world'),
    document.getElementById('root')
)

如果你使用了React.createElement的快捷方式,那么在没有JSX的情况下使用React一样方便。