在 React.js 中使用 ES6+
来源:互联网 发布:同业拆借 知乎 编辑:程序博客网 时间:2024/06/06 12:55
在今年对 Instagram Web 进行全新的设计的时候,我喜欢在写 React 组件的时候,用上一些 ES6+ 的新特性。请允许我列举这些能够改变你写 React 应用方式的新特性。比起以往,这些特性能够使你撸起码来更加容易、有趣!
类(Class)
使用 ES6+ 来编写 React 组件最明显的变化就是我们定义组件(类)的语法的方式。我们可以用定义一个继承了 React.Component
的ES6 类来代替原本使用 React.createClass
的来创建类的方式:
12345
class Photo extends React.Component { render() { return <img alt={this.props.caption} src={this.props.src} />; }}
我们可以发现这种写法使得定义组件的方式变得更加简洁:
12345678910
// The ES5 wayvar Photo = React.createClass({ handleDoubleTap: function(e) { … }, render: function() { … },});// The ES6+ wayclass Photo extends React.Component { handleDoubleTap(e) { … } render() { … }}
这样我们可以少写一对圆括号、一个分号、每个方法的冒号和 function
关键字。
所有生命周期方法都可以采用这种方式来定义。 但是 componentWillMount
还可以用 constructor
来代替:
1234567891011
// The ES5 wayvar EmbedModal = React.createClass({ componentWillMount: function() { … },});// The ES6+ wayclass EmbedModal extends React.Component { constructor(props) { super(props); // Operations usually carried out in componentWillMount go here }}
属性初始化(property initializers)
在 ES6+ 类中,属性类型 prop type
和默认属性 default prop
可以通过类中的 static
来声明。同时,组件的初始状态( initial state
)可以通过 ES7 的属性初始化(property initializers)来完成:
123456789101112131415161718192021222324252627282930313233343536
// The ES5 wayvar Video = React.createClass({ getDefaultProps: function() { return { autoPlay: false, maxLoops: 10, }; }, getInitialState: function() { return { loopsRemaining: this.props.maxLoops, }; }, propTypes: { autoPlay: React.PropTypes.bool.isRequired, maxLoops: React.PropTypes.number.isRequired, posterFrameSrc: React.PropTypes.string.isRequired, videoSrc: React.PropTypes.string.isRequired, },});// The ES6+ wayclass Video extends React.Component { static defaultProps = { autoPlay: false, maxLoops: 10, } static propTypes = { autoPlay: React.PropTypes.bool.isRequired, maxLoops: React.PropTypes.number.isRequired, posterFrameSrc: React.PropTypes.string.isRequired, videoSrc: React.PropTypes.string.isRequired, } state = { loopsRemaining: this.props.maxLoops, }}
ES7 中在构造函数( constructor
)下的属性初始化操作中的 this
指向的是类的实例,所以初始状态( initial state
)可以通过 this.prop
(即传入的参数)来设定。
箭头函数(Arrow function)
React.createClass
方法在你的组件上做了一些额外的绑定工作,以确保在组件实实例的方法内部, this
指向的是组件实例自身。
1234567
// Autobinding, brought to you by React.createClassvar PostInfo = React.createClass({ handleOptionsButtonClick: function(e) { // Here, 'this' refers to the component instance. this.setState({showOptionsModal: true}); },});
由于我们使用 ES6+ 的语法定义类的时候没有采用 React.createClass
的方式,所以,这样看来我们不得不手动来绑定这些方法中 this
的指向:
123456789101112
// Manually bind, wherever you need toclass PostInfo extends React.Component { constructor(props) { super(props); // Manually bind this method to the component instance... this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this); } handleOptionsButtonClick(e) { // ...to ensure that 'this' refers to the component instance here. this.setState({showOptionsModal: true}); }}
幸运的是,通过 ES6+ 的箭头函数( Arrow functions )和属性初始化( property initializers )这两个特性使得把函数的 this
指向绑定为组件的实例变得非常的简单:
12345
class PostInfo extends React.Component { handleOptionsButtonClick = (e) => { this.setState({showOptionsModal: true}); }}
函数体内的 this
对象,绑定定义时所在的对象,而不是使用时所在的对象。而恰好属性初始化( property initializers )刚好在这个作用域内。
动态属性名 & 字符串模板
在 ES6+ 中对 对象字面量的扩展 使得我们可以在对象字面量中使用表达式来对属性命名。如果是在 ES5 中,我们也许只能这样做:
1234567
var Form = React.createClass({ onChange: function(inputName, e) { var stateToSet = {}; stateToSet[inputName + 'Value'] = e.target.value; this.setState(stateToSet); },});
但是,在 ES6+ 中,我们不仅可以在对象字面量属性的定义中使用表达式,还有使用使用 字符串模板 :
1234567
class Form extends React.Component { onChange(inputName, e) { this.setState({ [`${inputName}Value`]: e.target.value, }); }}
析构 & 扩展运算符
我们在编写组件的过程中,经常遇到要从父组件要把自己的很多属性多传给子组件的情况。有了 ES6+ 的 析构 和扩展运算符 特性,这变得非常的方便:
1234567891011121314
class AutoloadingPostsGrid extends React.Component { render() { var { className, ...others, // contains all properties of this.props except for className } = this.props; return ( <div className={className}> <PostsGrid {...others} /> <button onClick={this.handleLoadMoreClick}>Load more</button> </div> ); }}
我们可以把 扩展运算符 属性和普通的属性结合起来使用,这样使得我们可以利用优先级来使用属性的默认值和属性的覆盖。下面这个元素会获得一个 override
的类( class
),及时 this.props
中有传递 className
属性。
123
<div {...this.props} className="override"> …</div>
下面这种写法,可以给元素设定默认的 className
:
123
<div className="base" {...this.props}> …</div>
最后
我希望你能够享受 ES6+ 的这些特性给你在编写 React.js 中带来的好处。感谢我的同事他们为这篇文章作出的贡献,还有,特别的感谢 Babel 团队,使得我们可以随意的使用这些特性。
- 在 React.js 中使用 ES6+
- 预备es6:在react中使用es6必懂的一些知识
- 【React】在React项目中使用parallax.js
- 在react中如何使用tab组件-小白系列 es6
- react使用es6(I)
- react 使用es6(II)
- React 不使用ES6
- 在node中使用 ES6
- React.js中常用的ES6写法总结
- React.js中ES6 和 ES5写法的一些差别
- React在ES6中的用法
- webpack.config.js中使用ES6语法
- 如何在React组建中使用百度地图api (react js)
- React中es6语法解析
- [译]使用 ES6+ 写 react
- MVC4中使用React.js入门
- 使用react.js中遇到的问题
- 1、React Native 中ES6语法解析
- ES6和原生js笔记
- C#关闭窗口方式以及线程后台运行
- Linux c编程--利润提成
- nginx监听事件流程
- 关于编写android程序遇到的问题
- 在 React.js 中使用 ES6+
- C字符串
- Exception thrown in catch and finally clause
- PHP单引号与双引号区别记录
- 使用Tomcat+Redis来实现集群部署中的Session共享问题
- 降雷皇 【NOIP2017提高组模拟12.10】
- poj_1200_Crazy Search_hash
- 三种设置session的失效时间
- Ubuntu等Linux系统显卡性能测试软件 Unigine 3D