0
点赞
收藏
分享

微信扫一扫

我的 React Native 技能树点亮计划 の React Native 从 ES5 到 ES6 的语法升级

ECMAScript 2015(为了行文简短起见,后文统称为 ES6)已经于 2015 年 6 月份正式发布,React 框架从 v0.13[1] 版本开始增加对 ES6 语法的支持,React Native 框架从 v0.18.0 版本开始,例子工程 AwesomeProject 的​​index.android.js​​​ 和 ​​index.ios.js​​ 中的语法也由之前版本的 ES5 语法切换到 ES6 语法。虽然官方没有明确说不鼓励 ES5 语法,但使用 ES6 代替 ES5 是大势所趋,为何不就现在开始做呢?在新开发的代码中,我们建议尽量使用 ES6 语法。下面就来具体说说 React Native 开发中哪些方面涉及到 ES5 语法到 ES6 语法的升级。

模块的导入

在 ES5 语法中,模块的导入使用 ​​require​​​ 语句,到了 ES6 则改用 ​​import​​ 语句,先来看下 ES5 语法:

let React = require('react-native');    
let {
AppRegistry,
StyleSheet,
Text,
View
} = React;

根据 ES6 语法修改如下:

import React, {    
AppRegistry,
StyleSheet,
Component,
Text,
View
} from 'react-native';

可以看到,使用 ES6 语法时,我们多导入了一个名为 ​​Component​​​ 的组件,从类的定义一节可以看出,这个 ​​Component​​​ 是 React 组件的基类。上面代码中是从 ​​react-native​​​ 包中导入 ​​React​​​ 和 ​​Component​​ 的,但这一做法从 React Native 的 v0.25.1[2]

import React, { Component } from 'react';    
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';

也就是说,​​React​​​ 和 ​​Component​​​ 等 React 相关的组件已经从 ​​react-native​​​包中独立出来并放到了名为 ​​react​​ 的包中。这一变化其实从 2015 年 10 月份发布的 React v0.14[3]

我的 React Native 技能树点亮计划 の React Native 从 ES5 到 ES6 的语法升级_github

如果你在 React Native v0.25.1 之前就已经使用 RN 进行开发,那么不可避免的会需要将 import 语法进行升级,手动修改当代码量较多时肯定是不现实的,可以使用开发者社区给出的自动转换方案 ​​codemod-RN24-to-RN25[4]​​。

模块的导出

在 ES6 语法中,模块的导出使用 ​​export default​​​ 代替 ​​module.exports​​,如下所示:

// ES5 语法   
var SwipeLayout = React.createClass({
...
});

module.exports = SwipeLayout;

// ES6 语法
export default SwipeLayout extends React.Component {
...
}

类的定义

从 ES6 开始引入了类的概念,我们通过关键字 ​​class​​​ 可以实现类的定义,本质上,ES6 中的 ​​class​​ 概念可以看作是一个语法糖,它使得开发者可以使用更面向对象的语法进行代码的编写。

ES5 中其实也是有类的概念的,只不过更多的是以模块作为称呼,ES5 中定义一个模块语法如下:

var F8App = React.createClass({    
componentDidMount: function() {//...},
componentWillUnmount: function() {//...},
render: function() {//...},
});

使用 ES6 语法进行改写,如下所示:

class F8App extends React.Component {    
constructor(props) {//...}
componentDidMount() {//...}
componentWillUnmount() {//...}
render() {//...}
}

可以看到,最明显的区别是 ES6 使用 ​​React.Component​​​ 来代替 ES5 的​​React.createClass​​​,同时,类中方法的定义不再需要尾随 ​​function​​​,而且方法之间不需要以 ​​,​​​ 分隔;同时增加了构造函数 ​​constructor​​。

成员变量的声明

使用 ES5 语法时,React Native 组件的成员变量声明方式如下所示:

let SwipeLayout = React.createClass({    
_panResponder:{},
_isExpanded:true,
_isSwiping:false,
...
});

当切换到 ES6 语法时,由于 ​​class​​ 引入了构造函数的概念,因此,成员变量的初始化都应该放在构造函数中,如下所示:

class SwipeLayout extends React.Component {    
constructor(props) {
super(props);
this._panResponder = {};
this._isExpanded = true;
this._isSwiping = false;
}
}

类的静态成员变量和静态成员函数的声明

ES5 语法中,在 React Native 组件中声明静态成员变量和静态成员函数的方式如下:

let F8HeaderIOS = React.createClass({    
statics: {
height : 100
verify : function() {
...
}
},
});

ES6 语法中定义如下所示:

class F8HeaderIOS extends React.Component {  
static height: 100;
static verify() {
...
}
}

属性的声明

在 ES5 语法中,React Native 组件中属性的声明和默认值的指定如下所示,是在组件内部声明的:

var MyComponent = React.createClass({    
propTypes: {
aStringProp: React.PropTypes.string
},
getDefaultProps: function() {
return { aStringProp: '' };
},
});

到了 ES6 的 ​​class​​​ 中,要求属性的类型声明和默认值声明移动到组件定义的外部实现,同时在 ​​class​​​ 类定义中将 ​​getDefaultProps​​​ 函数重构为一个属性​​defaultProps​​,转换为 ES6 语法之后的代码如下所示:

class MyComponent extends React.Component {...}    
MyComponent.propTypes = {
aStringProp: React.PropTypes.string
};
MyComponent.defaultProps = {
aStringProp: ''
};

状态的初始化

使用 ES5 语法时,React Native 组件的状态变量是在 ​​getInitialState​​ 函数中初始化的,如下所示:

let MyComponent = React.createClass({  
getInitialState: function() {
return {
scrollTop: new Animated.Value(0),
};
},
});

到了 ES6 语法中,React Native 团队修改了状态变量的初始化方式,取消了单独的 ​​getInitialState​​​ 函数,将初始化放在构造函数中,并提供 ​​this.state​​实例变量用来存储状态变量,如下所示:

class MyComponent extends React.Component {    
constructor(props) {
super(props);
this.state = {
scrollTop: new Animated.Value(0),
};
}
}

实例函数/回调函数的绑定

ES5 语法中,React Native 的 ​​createClass​​​ 函数提供的一个便利的功能是自动绑定类作用域中的函数到组件实例,例如 ​​createClass​​​ 里面定义的函数可以通过 ​​this​​ 直接指向本组件的某个成员函数,如下所示:

let MyComponent = React.createClass({    
_handleClick : function() { // 这个方法将作为回调函数使用
console.log('onClick');
},

render : function() {
return (
<View style={styles.container}>
<Text style={styles.normal}
onPress={this._handleClick}>
确定
</Text>
</View>
);
},
});

到了 ES6 的 ​​class​​ 定义中,开发者必须手动进行回调函数的绑定操作,React Native 团队推荐在组件的构造函数中进行,如下所示:

class MyComponent extends React.Component {    
constructor(props) {
super(props);
// 手动执行绑定操作
this._handleClick = this._handleClick.bind(this);
}

_handleClick() {
console.log('onClick');
}

render() {
return (
<View style={styles.container}>
<Text style={styles.normal}
onPress={this._handleClick}>
确定
</Text>
</View>
);
}
}

可以看到,如果 React Native 组件中存在多个回调函数需要进行 ​​bind​​ 操作,那么会存在较多的样板代码,如下所示:

class MyComponent extends React.Component {    
constructor(props) {
super(props);
// 手动执行绑定操作
this._handleClick = this._handleClick.bind(this);
this._handleTouch = this._handleTouch.bind(this);
...
}
}

为了减少样板代码的存在,提高开发效率,我们可以将 ​​bind​​​ 操作进行一次封装,提供一个 ​​BaseComponent​​ 的基类来简化绑定操作,如下所示:

class BaseComponent extends React.Component {    
_bind(...methods) {
methods.forEach( (method) => this[method].bind(this) );
}
}

class MyComponent extends BaseComponent {
constructor(props) {
super(props);
// 手动执行绑定操作
this._bind('_handleClick', '_handleTouch');
}
}

Mixins

我们知道 ES5 语法中使用 ​​React.createClass​​​ 是支持 Mixins 的,我们可以通过给 ​​mixins​​ 属性赋值从而给对应的组件添加 Mixins 能力,可以添加多个 Mixins,如下所示:

var SomeMixin = {    
doSomething() {

}
};

var F8SessionDetails = React.createClass({
mixins: [SomeMixin],

getInitialState: function() {
return {
scrollTop: new Animated.Value(0),
};
},
...
});

当你切换到 ES6 中的 ​​class​​ 时 Mixins 功能不可用。

拓展阅读

《Refactoring React Components to ES6 Classes》[5] [6] [7] [8] [9] [10] [11]

欢迎关注我的微信公众号 ASCE1885,专注与原创或者分享 Android,iOS,ReactNative,Web 前端移动开发领域高质量文章,主要包括业界最新动态,前沿技术趋势,开源函数库与工具等。

我的 React Native 技能树点亮计划 の React Native 从 ES5 到 ES6 的语法升级_github_02

[1] https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html ↩[2] https://github.com/facebook/react-native/releases/tag/v0.25.1 ↩[3] https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html ↩[4] https://github.com/sibelius/codemod-RN24-to-RN25 ↩[5] http://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes ↩[6] http://www.wangchenlong.org/2016/04/26/1604/261-rn-es6-class/ ↩[7] http://egorsmirnov.me/2015/05/22/react-and-es6-part1.html ↩[8] http://moduscreate.com/how-to-use-es6-arrow-functions-with-react-native/↩[9] http://www.ghugo.com/react-native-es6/ ↩[10] https://toddmotto.com/react-create-class-versus-component/ ↩[11] https://babeljs.io/blog/2015/06/07/react-on-es6-plus ↩

举报

相关推荐

0 条评论