React类、ES7属性初始化(第二部分)
这是React和ECMAScript6结合使用系列文章的第二篇。 下面是所有系列文章章节的链接:
在第一篇文章中,我们开始介绍如何使用ES6来创建静态的组建并且输出 在这篇文章中,我们将创建一个名字叫做 此外,用户可以和 最后的项目效果图:
创建index.html文件让我们来创建一个简单的html模版文件。 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>React and ES6 Part 2</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/5.5.2/css/foundation.min.css"> </head> <body> <div class="root"></div> <script src="dist/bundle.js"></script> </body> </html> 注意我们已经通过 Gulpfile.js创建 var gulp = require('gulp'); var browserify = require('browserify'); var babelify = require('babelify'); var source = require('vinyl-source-stream'); gulp.task('build',function () { return browserify({entries: './app.jsx',extensions: ['.jsx'],debug: true}) .transform('babelify',{presets: ['es2015','react']}) .bundle() .on('error',function(err) { console.error(err); this.emit('end'); }) .pipe(source('bundle.js')) .pipe(gulp.dest('dist')); }); gulp.task('watch',['build'],function () { gulp.watch('*.jsx',['build']); }); gulp.task('default',['watch']); package.json
Main application React Component创建 import React from 'react'; import ReactDOM from 'react-dom'; import CartItem from './cartItem'; const order = { title: 'Fresh fruits package',image: 'http://images.all-free-download.com/images/graphiclarge/citrus_fruit_184416.jpg',initialQty: 3,price: 8 }; ReactDOM.render( <CartItem title={order.title} image={order.image} initialQty={order.initialQty} price={order.price}/>,document.querySelector('.root') ); 上面的代码做了什么:
CartItem React Component 架构现在是创建负责显示项目的数据以及与用户的交互组件的时候了。 添加下面的代码到 import React from 'react'; export default class CartItem extends React.Component { constructor(props) { super(props); this.state = { qty: props.initialQty,total: 0 }; } componentWillMount() { this.recalculateTotal(); } increaseQty() { this.setState({qty: this.state.qty + 1},this.recalculateTotal); } decreaseQty() { let newQty = this.state.qty > 0 ? this.state.qty - 1 : 0; this.setState({qty: newQty},this.recalculateTotal); } recalculateTotal() { this.setState({total: this.state.qty * this.props.price}); } } 代码解释:
CartItem render method在 export default class CartItem extends React.Component { // previous code we wrote here render() { return ( <article className="row large-4"> <figure className="text-center"> <p> <img src={this.props.image}/> </p> <figcaption> <h2>{this.props.title}</h2> </figcaption> </figure> <p className="large-4 column"><strong>Quantity: {this.state.qty}</strong></p> <p className="large-4 column"> <button onClick={this.increaseQty.bind(this)} className="button success">+</button> <button onClick={this.decreaseQty.bind(this)} className="button alert">-</button> </p> <p className="large-4 column"><strong>Price per item:</strong> ${this.props.price}</p> <h3 className="large-12 column text-center"> Total: ${this.state.total} </h3> </article> ) } } 这里我们只是使用JSX+组建,再加上一些基础的CSS输出漂亮的标签。 不要担心 因此,到现在我们已经有了和用户交互的漂亮的应用了,它向我们展示了如何使用 到现在我们还没有完成。在完成这篇文章之前,我们将再看看ES6中其它的一些新的特性。 Default Props and Prop Types for ES6 React classes想象我们想要为CartItem组建添加一些验证和默认值。 幸运的是,你只需要在 static get defaultProps() { return { title: 'Undefined Product',price: 100,initialQty: 0 } } static propTypes = { title: React.PropTypes.string.isRequired,price: React.PropTypes.number.isRequired,initialQty: React.PropTypes.number } PS: 也可以将上面的代码删除,在 CartItem.defaultProps = { title: 'Undefined Product',initialQty: 0 } CartItem.propTypes = { title: React.PropTypes.string.isRequired,initialQty: React.PropTypes.number } 就我个人而言,比较喜欢第一种写法,它不会破坏类的封装性。 添加上面的代码后,如果你给 Bringing ES7 into the project你可能会问一个合理的问题,为什么ES6还没有定稿,在你的标题中为什么出现ES7呢? 我会告诉你,让我们展望未来。我们开始使用non-breaking、property initializers和decorators的新特性。 即使ES7还处于非常早期的阶段,在Babel中已经实现了部分的建议性的新特性。这些实验性的新特性是从ES5到ES7令人惊叹的新的特性的转变。 首先,通过 其次,为了在我们项目中能够使用新的语法,我们需要在 .transform('babelify',{presets: ['react','es2015','stage-0']}) 你可以从GitHub repository直接拷贝 ES7 React 组建属性初始化/默认值/类型Inside class add this right above : 在 static get defaultProps() { return { title: 'Undefined Product',initialQty: React.PropTypes.number } 替换成下面的代码: static propTypes = { title: React.PropTypes.string.isRequired,initialQty: React.PropTypes.number }; static defaultProps = { title: 'Undefined Product',initialQty: 0 }; ES7 Property Initialiazers for initial state of React component最后一步将初始状态从构造函数中转变成属性初始化。 在 export default class CartItem extends React.Component { // .. constructor starts here state = { qty: this.props.initialQty,total: 0 }; // .. some code here 你需要把状态初始化代码从构造函数中删除。 最后你需要检查一下 import React from 'react'; export default class CartItem extends React.Component { constructor(props) { super(props); } state = { qty: this.props.initialQty,total: 0 }; static propTypes = { title: React.PropTypes.string.isRequired,initialQty: React.PropTypes.number }; static defaultProps = { title: 'Undefined Product',initialQty: 0 }; componentWillMount() { this.recalculateTotal(); } increaseQty() { this.setState({qty: this.state.qty + 1},this.recalculateTotal); } recalculateTotal() { this.setState({total: this.state.qty * this.props.price}); } render() { return ( <article className="row large-4"> <figure className="text-center"> <p> <img src={this.props.image}/> </p> <figcaption> <h2>{this.props.title}</h2> </figcaption> </figure> <p className="large-4 column"><strong>Quantity: {this.state.qty}</strong></p> <p className="large-4 column"> <button onClick={this.increaseQty.bind(this)} className="button success">+</button> <button onClick={this.decreaseQty.bind(this)} className="button alert">-</button> </p> <p className="large-4 column"><strong>Price per item:</strong> ${this.props.price}</p> <h3 className="large-12 column text-center"> Total: ${this.state.total} </h3> </article> ) } } 结论在这一节中,我们熟练掌握了ES6和ES7 React组建属性的初始化,类型绑定。 下一小结,我们继续研究React+ES6系列教程。 参考文档
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |