资讯专栏INFORMATION COLUMN

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

VioletJack / 582人阅读

摘要:组建属性初始化默认值类型在中将下面的代码替换成下面的代码最后一步将初始状态从构造函数中转变成属性初始化。在构造函数的后天添加正确的代码你需要把状态初始化代码从构造函数中删除。

这是React和ECMAScript6结合使用系列文章的第二篇。

下面是所有系列文章章节的链接:

React 、 ES6 - 介绍(第一部分)

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

React类,方法绑定(第三部分)

ES6中React Mixins的使用(第四部分)

React 和ES6 之JSPM的使用(第五部分)

React 和 ES6 工作流之 Webpack的使用(第六部分)

本篇文章Github源码

React JS

在第一篇文章中,我们开始介绍如何使用ES6来创建静态的组建并且输出Hello from ES6. Not so exciting :)

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

此外,用户可以和CartItem组建交互,通过点击增加或者减少改变items的数量。并且我们的组建将对交互后的总价格做出动态改变。

最后的项目效果图:

创建index.html文件

让我们来创建一个简单的html模版文件。




    
    React and ES6 Part 2
    


注意我们已经通过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,这将安装reactreact-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(
    ,
    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 (
          

{this.props.title}

Quantity: {this.state.qty}

Price per item: ${this.props.price}

Total: ${this.state.total}

) } }

这里我们只是使用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 (
          

{this.props.title}

Quantity: {this.state.qty}

Price per item: ${this.props.price}

Total: ${this.state.total}

) } }
结论

在这一节中,我们熟练掌握了ES6和ES7 React组建属性的初始化,类型绑定。

下一小结,我们继续研究React+ES6系列教程。

参考文档

Props vs state in React

About Prop Validation and more, official React documentation

About experimental features in BabelJS

ES7 Class Properties Proposal

扫码申请加入全栈部落

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83983.html

相关文章

  • React,方法绑定(三部

    摘要:使用箭头函数和构造函数当方法被调用时,会保留上下文。我们能使用这个特征用下面的方法在构造函数中重定义函数。在调用方法的方使用函数绑定语法你也可以直接在非构造函数里面的里面直接使用函数绑定。 这是React和ECMAScript6/ECMAScript7结合使用系列文章的第三篇。 下面是所有系列文章章节的链接: React 、 ES6 - 介绍(第一部分) React类、ES7属性初始...

    livem 评论0 收藏0
  • ES6中React Mixins的使用(四部

    摘要:在的组建创建中,不太可能使用混合机制。在中,这个组建将被命名为。他们中的其中一个如下结论高阶组建功能强大和极具表现力。现在高阶组建广泛的被使用来替代老式的句法。 这是React和ECMAScript6/ECMAScript7结合使用系列文章的第四篇。 下面是所有系列文章章节的链接: React 、 ES6 - 介绍(第一部分) React类、ES7属性初始化(第二部分) React类...

    Karrdy 评论0 收藏0
  • React 、 ES6 - 介绍(一部

    摘要:下一步我们将结果输出到文件。这是我们用编写的第一个非常简单的组建。使用将创建的组建导出以便在其它地方能够正常导入使用。 这是React和ECMAScript6结合使用系列文章的第一篇。 本文出自从零到壹全栈部落 下面是所有系列文章章节的链接: React 、 ES6 - 介绍(第一部分) React类、ES7属性初始化(第二部分) React类,方法绑定(第三部分) ES6中Reac...

    pingink 评论0 收藏0
  • ES6 系列之我们来聊聊装饰器

    摘要:第二部分源码解析接下是应用多个第二部分对于一个方法应用了多个,比如会编译为在第二部分的源码中,执行了和操作,由此我们也可以发现,如果同一个方法有多个装饰器,会由内向外执行。有了装饰器,就可以改写上面的代码。 Decorator 装饰器主要用于: 装饰类 装饰方法或属性 装饰类 @annotation class MyClass { } function annotation(ta...

    eternalshallow 评论0 收藏0
  • React 和ES6 之JSPM的使用(五部

    摘要:让为生产研发的使用准备相关文件变得更容易。在这篇文章中,我们将重新创建和之前一样的新的项目,但是我们使用。让我们安装其它我们将要使用的依赖包在这里我们没有使用或者前缀,因为有常用包的注册表。 这是React和JSPM结合使用系列文章的第五篇。 下面是所有系列文章章节的链接: React 、 ES6 - 介绍(第一部分) React类、ES7属性初始化(第二部分) React类,方法绑...

    zzbo 评论0 收藏0

发表评论

0条评论

VioletJack

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<