值此七夕佳节
,在这里记录一下今天用React写一个倒计时组件的笔记。
实现功能
基于ES6
用React
实现一个倒计时组件,格式:6时6分6秒,然后每隔一秒不断倒计时。
回顾Mixins
当然,完全可以直接写在一个React.createClass
函数里面,但可复用性
不高,所以换做在之前官方推荐的做法就是利用Mixins特性,所谓Mixins我理解就是注入
,类似于Java Spring
的依赖注入
,简单代码如下:
var SetIntervalMixin = { componentWillMount: function() { this.intervals = []; }, setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, componentWillUnmount: function() { this.intervals.forEach(clearInterval); } };
var Timer = React.createClass({ mixins: [SetIntervalMixin], getInitialState: function() { return { timestamp: this.props.timestamp } }, componentDidMount: function() { this.setInterval(this.changeState, 1000); }, changeState: function() { this.setState({ timestamp: this.state.timestamp - 1000 }) }, render: function() { var timestamp = this.state.timestamp; return <p>{this.renderTime(timestamp)}</p> }, renderTime(timestamp){ ... return 'XX天XX时XX分XX秒'; } });
ReactDOM.render( <Timer timestamp="66666666"/> , document.querySelector("body") );
|
用Mixins
的最大好处就是复用
,保证组件的最小颗粒化,同时也保证了功能相对单一。
ES6的高阶函数
但是用ES6
来写的话,Mixins
显得有点无力,没有办法注入,这个时候高阶函数就派上用场了,其实Redux
的connect
就是利用了这一特性,改写上面的代码如下:
var SetIntervalMixin = ComposedComponent => class extends React.Component { constructor(props) { super(props); this.state = { timestamp: this.props.timestamp } } componentDidMount() { this.interval = setInterval(this.changeState.bind(this), 1000); } componentWillUnmount() { clearInterval(this.interval); } changeState() { this.setState({ timestamp: this.state.timestamp - 1000 }); } render() { return <ComposedComponent {...this.props} {...this.state} />; } };
class Timer extends React.Component { constructor(props) { super(props); } render() { var timestamp = this.props.timestamp; return <p>{this.renderTime(timestamp)}</p> } renderTime(timestamp){ ... return 'XX天XX时XX分XX秒'; } } export default SetIntervalMixin(Timer);
ReactDOM.render( <Timer timestamp="66666666"/> , document.querySelector("body") );
|
总结
两者方法其实我更倾向于第二种,也不单单是用ES6
写起来舒服些,函数式编程
以及中间件
的思维在里面,总而言之,写组件多考虑抽取可复用
组件出来,避免逻辑一大堆糅合在一起。
稍微再记一下今天碰到的一个坑:用ES6
的for...of
去遍历数组的时候,利用Babel
转换在chrome 49
以下会被转换成Symbol
导致报错 o(╯□╰)o