React类、ES7属性初始化(第二部份)

这是React和ECMAScript6连系运用系列文章的第二篇。

下面是一切系列文章章节的链接:

本篇文章Github源码

ReactJS
《React类、ES7属性初始化(第二部份)》《React类、ES7属性初始化(第二部份)》

第一篇文章中,我们最先引见怎样运用ES6来建立静态的组建而且输出Hello from ES6. Not so exciting :)

在这篇文章中,我们将建立一个名字叫做CartItem的更庞杂的组建。它将输出购物车中的一些产品信息,包含图片、题目和价钱。

另外,用户可以和CartItem组建交互,经由过程点击增添或许削减改变items的数目。而且我们的组建将对交互后的总价钱做出动态改变。

末了的项目效果图:

《React类、ES7属性初始化(第二部份)》

建立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

  1. 建立一个空文件夹,切换到这个文件夹中,在终端输入npm init初始化你的package.json

  2. 运转npm install --save react react-dom,这将装置reactreact-dom到你的node_modules文件夹而且作为依靠库保存到package.json文件中。

  3. 运转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系列教程。

参考文档

扫码申请加入全栈部落
《React类、ES7属性初始化(第二部份)》
    原文作者:愿码社区技术团队
    原文地址: https://segmentfault.com/a/1190000010185055
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞