React学习(8)—— 高阶应用:不使用ES6、JSX实现React
2017-04-07 00:00
489 查看
摘要: 记录学习JSX+ES6开发React的第八篇,按照官网的思路介绍如何使用React开发。
如果不使用ES6语法,可以直接使用
在使用
在使用
在使用
以上的特性意味着使用ES6编写代码每一个方法都会额外增加一些样板式代码,但是对于大型应用来说代码结构更清晰。
如果十分排斥样板式代码,可以启用Babal的 类属性功能( Class Properties ),利用双箭头来创建方法:
需要注意的是,目前这个功能还是实验性的,双箭头的表达式很有可能会调整。该提议不一定会被委员会接纳。
如果非常想要尝试这种写法,你可以有这几种实现方式:
在构造函数中绑定方法。
使用箭头来定义方法。
使用
ES6在目前的方案中并不支持代码混合功能,因此在使用ES6编写React代码时并不能实现相关功能。
官方也收到许多在使用混合器时遇到的问题,强烈建议不要在新的代码中使用混合器功能。
以下的内容仅供参考。
某些时候2个不同的组件需要共享一些相同的方法或者功能。这种情况我们称为 横切关联( cross-cutting concerns)。
一个通用的案例是一个组件需要定期更新自己的状态,只要使用
如果组件使用了多个混合器并且很多混合器定义了相同的生命周期方法,比如同时定义了componentWillUnmount方法当组件卸载时注销某些资源。所有混合器的生命周期方法都会被调用,React会按照混合器设定的顺序来执行。
每一个JSX的元素都仅仅是
例如下面使用JSX编码的例子:
如果我们不想使用JSX,可以将其修改为:
如果你对JSX如何转换成JavaScript有很强的兴趣,可以打开这个在线编译器试试:the online Babel compiler。
组件被编译成一段字符串、由
如果对编码时每次都要键入长长React.createElement感到痛苦,一个常见的模式是分配一个别名:
不使用ES6
通常情况下,定义一个React组件可以使用ES6规范中的class关键字:class Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
如果不使用ES6语法,可以直接使用
React.createClass来实现相同的功能:
var Greeting = React.createClass({ render: function() { return <h1>Hello, {this.props.name}</h1>; } });
声明Prop的检查类型以及默认Props值
在前面的博文(prop类型检查与真实Dom操作)中介绍了如何规约Prop的参数值,给出的例子都是用ES6实现的:class Greeting extends React.Component { // ... } Greeting.propTypes = { name: React.PropTypes.string }; Greeting.defaultProps = { name: 'Mary' };
在使用
React.createClass时,可以通过设定传入的对象的一个属性值——
propTypes来指定参数类型,通过
getDefaultProps()方法来设定每个参数的默认值:
var Greeting = React.createClass({ propTypes: { name: React.PropTypes.string }, getDefaultProps: function() { return { name: 'Mary' }; }, // ... });
设定初始化状态
在ES6的 class 结构中,我们可以在构造函数中设定初始化状态:class Counter extends React.Component { constructor(props) { super(props); this.state = {count: props.initialCount}; } // ... }
在使用
React.createClass时,可以为传入的对象参数添加一个
getInitialState方法并返回一个初始状态值:
var Counter = React.createClass({ getInitialState: function() { return {count: this.props.initialCount}; }, // ... });
自动绑定
当使用ES6的 class 关键字声明一个React组件时,类中的方法遵循与常规的方法一样的定义。这就意味着在类中申明的方法在执行时并不会自动属于当前实例,必须在构造函数中显示的使用.bind(this)方法绑定到当前实例:class SayHello extends React.Component { constructor(props) { super(props); this.state = {message: 'Hello!'}; // 必须,否在在handleClick中this将指向调用对象 this.handleClick = this.handleClick.bind(this); } handleClick() { alert(this.state.message); } render() { return ( <button onClick={this.handleClick}> Say hello </button> ); } }
在使用
React.createClass时不必绑定所有的方法:
var SayHello = React.createClass({ getInitialState: function() { return {message: 'Hello!'}; }, handleClick: function() { alert(this.state.message); }, render: function() { return ( <button onClick={this.handleClick}> Say hello </button> ); } });
以上的特性意味着使用ES6编写代码每一个方法都会额外增加一些样板式代码,但是对于大型应用来说代码结构更清晰。
如果十分排斥样板式代码,可以启用Babal的 类属性功能( Class Properties ),利用双箭头来创建方法:
class SayHello extends React.Component { constructor(props) { super(props); this.state = {message: 'Hello!'}; } handleClick = () => { alert(this.state.message); } render() { return ( <button onClick={this.handleClick}> Say hello </button> ); } }
需要注意的是,目前这个功能还是实验性的,双箭头的表达式很有可能会调整。该提议不一定会被委员会接纳。
如果非常想要尝试这种写法,你可以有这几种实现方式:
在构造函数中绑定方法。
使用箭头来定义方法。
使用
React.createClass。
代码混合器
注意:ES6在目前的方案中并不支持代码混合功能,因此在使用ES6编写React代码时并不能实现相关功能。
官方也收到许多在使用混合器时遇到的问题,强烈建议不要在新的代码中使用混合器功能。
以下的内容仅供参考。
某些时候2个不同的组件需要共享一些相同的方法或者功能。这种情况我们称为 横切关联( cross-cutting concerns)。
React.createClass可以通过继承来实现组件间公用相同方法。
一个通用的案例是一个组件需要定期更新自己的状态,只要使用
setInterval()就可以实现。但是当您不再需要它来节省内存时,取消定时器是很重要的。React提供了生命周期方法来通知创建和销毁事件。下面的代码创建了一个肩带的混合器,混合器的作用是当组件被销毁之前,可以清除已有的定时器:
// 定义一个混合器 var SetIntervalMixin = { //组件将要被渲染时调用 componentWillMount: function() { this.intervals = []; }, // 设置定时器方法 setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, //组件将要被卸载时调用 componentWillUnmount: function() { this.intervals.forEach(clearInterval); } }; var TickTock = React.createClass({ mixins: [SetIntervalMixin], // 设定混合器 getInitialState: function() { return {seconds: 0}; }, componentDidMount: function() { this.setInterval(this.tick, 1000); // 调用混合器中的setInterval 方法 }, tick: function() { this.setState({seconds: this.state.seconds + 1}); }, render: function() { return ( <p> React has been running for {this.state.seconds} seconds. </p> ); } }); ReactDOM.render( <TickTock />, document.getElementById('example') );
如果组件使用了多个混合器并且很多混合器定义了相同的生命周期方法,比如同时定义了componentWillUnmount方法当组件卸载时注销某些资源。所有混合器的生命周期方法都会被调用,React会按照混合器设定的顺序来执行。
不使用JSX
对于React来说JSX并不是必须要使用的表达式。当在环境中不想在家额外的编译工具时尤其适用。每一个JSX的元素都仅仅是
React.createElement(component, props, ...children)的语法糖,所以任何使用JSX表达式实现的内容都可以直接用JavaScript来实现。
例如下面使用JSX编码的例子:
class Hello extends React.Component { render() { return <div>Hello {this.props.toWhat}</div>; } } ReactDOM.render( <Hello toWhat="World" />, document.getElementById('root') );
如果我们不想使用JSX,可以将其修改为:
class Hello extends React.Component { render() { return React.createElement('div', null, `Hello ${this.props.toWhat}`); } } ReactDOM.render( React.createElement(Hello, {toWhat: 'World'}, null), document.getElementById('root') );
如果你对JSX如何转换成JavaScript有很强的兴趣,可以打开这个在线编译器试试:the online Babel compiler。
组件被编译成一段字符串、由
React.Component创建的子类或者一个普通无状态的组件。
如果对编码时每次都要键入长长React.createElement感到痛苦,一个常见的模式是分配一个别名:
const e = React.createElement; ReactDOM.render( e('div', null, 'Hello World'), document.getElementById('root') );
相关文章推荐
- 学习使用React一步步搭建普通博客应用
- 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(二)
- 使用scss + react + webpack + es6实现幻灯片
- SMP3.0学习笔记之八 使用Kapsel Update插件实现移动应用的自动更新
- 基于ES6,使用React、Webpack、Babel构建模块化JavaScript应用
- React学习笔记:使用jquery实现动画效果淡入淡出
- React学习——JSX的使用
- 5分钟内使用React、Webpack与ES6构建应用
- 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(一)
- 十八、不使用JSX编写React应用
- 使用express、react、webpack打包、socket.io、mongodb、ant.design、less、es6实现聊天室
- React学习笔记_ReactRedux应用使用AsyncAwait
- 十七、不使用ES6编写React应用
- 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)
- 使用PouchDB来实现React离线应用
- 使用react-native做一个简单的应用-06商品界面的实现
- 深入浅出React之第七章:使用React-Router实现多页面应用
- 使用Log4j为项目配置日志输出应用详解以及示例演示的实现分析
- Atlas学习手记(18):使用DragPanel实现拖放面板
- Atlas学习手记(7):使用DragOverlayExtender实现拖放功能