这是React和ECMAScript6连系运用系列文章的第二篇。
下面是一切系列文章章节的链接:
React | JS |
---|---|
在第一篇文章中,我们最先引见怎样运用ES6来建立静态的组建而且输出Hello from ES6
. Not so exciting :)
在这篇文章中,我们将建立一个名字叫做CartItem
的更庞杂的组建。它将输出购物车中的一些产品信息,包含图片、题目和价钱。
另外,用户可以和CartItem
组建交互,经由过程点击增添
或许削减
改变items的数目。而且我们的组建将对交互后的总价钱做出动态改变。
末了的项目效果图:
建立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>
注重我们已经由过程cdn
增加了Foundation CSS框架效劳.它可以让我们微运用看起来很美丽。同时,class为root的div将是我们运用加载的处所。
Gulpfile.js
建立gulpfile.js
文件,拷贝下面的代码到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
建立一个空文件夹,切换到这个文件夹中,在终端输入
npm init
初始化你的package.json
。运转
npm install --save react react-dom
,这将装置react
和react-dom
到你的node_modules
文件夹而且作为依靠库保存到package.json
文件中。运转
npm install --save-dev gulp browserify babelify vinyl-source-stream babel-preset-es2015 babel-preset-react
,这将装置更多的依靠到你的node_modules
文件夹。
Main application React Component
建立app.jsx
:
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')
);
上面的代码做了什么:
Lines 1-2. 我们导入 React / ReactDOM 库。
Line 3. 导入我们立时要建立的
CartItem
组建。Lines 5-10. 给
CartItem
组建设置相干属性(属性包含 item title, image, initial quantity and price).Lines 12-18. 加载CartItem组建到一个CSS类为root的DOM元素上。
CartItem React Component 架构
如今是建立担任显现项目的数据以及与用户的交互组件的时刻了。
增加下面的代码到cartItem.jsx
文件中:
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});
}
}
代码诠释:
Lines 4-10. 这是ES6中React类的组织函数。super(props)这句代码是先处置惩罚父类的props,这句代码必不可少。下面的状况机变量的设置相当于ES5中
getInitialState()
要领状况机变量的初始化,我们经由过程this.state
来给状况机变量设置初始值。个人看法,我比较喜好ES6中组织函数的写法。Lines 11-13.
componentWillMount()
是生命周期中的要领,在这个要领内里我们经由过程recalculateTotal()
要领对总价钱做了盘算。Lines 14-20. 给用户供应增添和削减的交互要领。当用户点击响应的按钮(如前面的效果图所示)时,这两个要领会被挪用。
CartItem render method
在CartItem
类中增加新的要领:
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输出美丽的标签。
不要忧郁{this.increaseQty.bind(this)}
这句代码的运用,下一小结中我们将会细致解说,如今你须要置信我,这句代码会挪用CartItem
类中的increaseQty()
要领即可。
因而,到如今我们已有了和用户交互的美丽的运用了,它向我们展现了怎样运用ECMAScript6
来编写React 组建。就我个人而言,我很喜好ES6带来的新的语法。
到如今我们还没有完成。在完成这篇文章之前,我们将再看看ES6中别的的一些新的特征。
Default Props and Prop Types for ES6 React classes
设想我们想要为CartItem组建增加一些考证和默认值。
荣幸的是,你只须要在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
内里非CartItem
类的内部增加以下代码:
CartItem.defaultProps = {
title: 'Undefined Product',
price: 100,
initialQty: 0
}
CartItem.propTypes = {
title: React.PropTypes.string.isRequired,
price: React.PropTypes.number.isRequired,
initialQty: React.PropTypes.number
}
就我个人而言,比较喜好第一种写法,它不会损坏类的封装性。
增加上面的代码后,假如你给title
属性增加numeric
范例的值,将在控制台涌现正告,这就是React属性考证的功用。
Bringing ES7 into the project
你可能会问一个合理的题目,为何ES6还没有定稿,在你的题目中为何涌现ES7呢?
我会通知你,让我们展望未来。我们最先运用non-breaking、property initializers和decorators的新特征。
纵然ES7还处于异常初期的阶段,在Babel中已完成了部份的建议性的新特征。这些实验性的新特征是从ES5到ES7令人惊叹的新的特征的改变。
起首,经由过程npm install --save-dev babel-preset-stage-0
敕令装置缺失的npm module
。
其次,为了在我们项目中可以运用新的语法,我们须要在gulpfile.js
文件的第8
行做一些改变,代码以下:
.transform('babelify', {presets: ['react', 'es2015', 'stage-0']})
你可以从GitHub repository直接拷贝gulpfile.js
完全的代码。
ES7 React 组建属性初始化/默认值/范例
Inside class add this right above :
在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
}
替换成下面的代码:
static propTypes = {
title: React.PropTypes.string.isRequired,
price: React.PropTypes.number.isRequired,
initialQty: React.PropTypes.number
};
static defaultProps = {
title: 'Undefined Product',
price: 100,
initialQty: 0
};
ES7 Property Initialiazers for initial state of React component
末了一步将初始状况从组织函数中改变成属性初始化。
在CartItem
组织函数的后天增加准确的代码:
export default class CartItem extends React.Component {
// .. constructor starts here
state = {
qty: this.props.initialQty,
total: 0
};
// .. some code here
你须要把状况初始化代码从组织函数中删除。
末了你须要检查一下cartItem.jsx
文件内里完全的代码:
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,
price: React.PropTypes.number.isRequired,
initialQty: React.PropTypes.number
};
static defaultProps = {
title: 'Undefined Product',
price: 100,
initialQty: 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});
}
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系列教程。
参考文档
扫码申请加入全栈部落 |
---|