zoukankan      html  css  js  c++  java
  • React和ES6(二)ES6的类和ES7的property initializer

    React与ES6系列:

    1. React与ES6(一)开篇介绍
    2. React和ES6(二)ES6的类和ES7的property initializer
    3. React与ES6(三)ES6类和方法绑定
    4. React与ES6(四)ES6如何处理React mixins

    前一篇的内容太简单了,会不会很失望。这次就来一个接近实际应用的例子,对应的React的组件也会更加复杂。这次开发一个购物车的页面。在这个页面中你会看到某个产品的信息,比如:图片、名称和价格。另外,一个用户可以增加和减少该商品的数量。

    创建cart_item.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 id="root"></div>
    <script src="public/cart.bundle.js" type="text/javascript"></script>
    </body>
    </html>
    

    我们使用了一个CDN来引用样式。添加个样式美化一下这个小应用的内容。dev.root会用来展示React组件生成的内容。

    CartItem组件

    现在开发Cart组件。创建文件cart.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.getElementById('root')
    );
    

    cart.jsx作为购物车功能的总容器。这里引入了reactreact-dom。之后引入了CartItem组件,这个组件会在稍后给出定义。最后,在ReactDom.render方法中把CartItem组件展示在class等于root的HTML元素中。

    CartItem组件中的title、image、initialQty和price都是props的值。这些值会在后面CartItem组件的定义中用到。props是组件给子组件传递数据的一种方式。

    CartItem组件初步定义

    现在应该给出CartItem的定义了。否则整个web app都无法正常运行。CartItem组件可以展示数据,也可以相应用户的增加、减少操作。

    import React from 'react';
    
    export default class CartItem extends React.Component {
        // 1
        constructor(props) {
            super(props);
            this.state = {
                qty: props.initialQty,
                total: 0
            };
        }
        // 2
        componentWillMount() {
            this.recalculateTotal();
        }
        // 3
        increaseQty() {
            this.setState({qty: this.state.qty + 1}, this.recalculateTotal);
        }
        // 3
        decreaseQty() {
            let newQty = this.state.qty > 0 ? this.state.qty - 1 : 0;
            this.setState({qty: newQty}, this.recalculateTotal);
        }
        // 3
        recalculateTotal() {
            this.setState({total: this.state.qty * this.props.price});
        }
    
        render() {
            return (
                // ...略...  
            );
        }
    }
    

    下面解释一下:

    1. constructor是ES6中类的构造函数。整个构造函数需要一个参数props,其全部的值都在上文的代码中给出:title、image等。需要注意的是在构造函数中第一个调用的是super(props)this.state = ...一句中,使用props初始化了整个组件的state初值。
    2. ·componentWillMount()方法是组件的生命周期方法之一。在组件即将在HTML页面中绘制的时候调用。在componentWillMount()中使用方法recalculateTotal()`计算了商品的总价。
    3. 这些是增加、减少商品数量的方法。这些方法在用户点击了增加、减少按钮之后被调用。在这些方法中,更新了state中物品数量的值,并在setState方法的回调中使用了recalculateTotal()方法。

    CartItem的render方法

    上一节没有给出render方法的具体实现,这里给出:

    import React from 'react';
    
    export default class CartItem extends React.Component {
        // ...略...
    
        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>
            );
    
        }
    }
    

    render()方法中,我们使用了JSX语法添加了各种“HTML”节点。这些节点和HTML标签很像,但是并不是HTML元素。

    不用担心this.decreaseQty.bind(this)之类的用法。这些会在下一篇里详细解释。

    React在ES6中的Default Props和Props类型

    假设我们现在需要给CartItem添加一些默认的props,并可以自动检查props的类型。

    幸好这些在React里都有内置支持。所以,相关代码非常少。

    CartItem类定义的下面直接添加下面的代码:

    CartItem.propTypes = {
        title: React.PropTypes.string.isRequired,
        price: React.PropTypes.number.isRequired,
        initialQty: React.PropTypes.number
    };
    
    CartItem.defaultProps = {
        title: "Indefined Product",
        price: 100,
        initialQty: 0
    };```
    这时候如果你在*cart.jsx*文件中给`CartItem`的title值为数值的话,你就会在浏览器中看到警告。
    
    ##在项目中使用ES7
    你可能要问了ES6还没整明白的就开始用上ES7了?我要说的是我们往前看,使用一些已经在静态语言里有的特性并不会造成太大的问题。最关键的问题是`Babel`已经支持了。
    
    首先安装必要的`Babel`模块:`npm install --save-dev babel-preset-stage-0`。
    
    然后在*.babelrc*文件中添加这个preset的配置:
    ```js
    {
        "presets": ["es2015", "react", "stage-0"]
    }
    

    ES7属性初始化器和React组件的Default Props、Props Types

    CartItem类里,添加如下代码:

    export default class CartItem extends React.Component {
        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
        };
    
        constructor(props) {
            super(props);
            this.state = {
                qty: props.initialQty,
                total: 0
            };
        }
    
    // ...略...
    

    这样的定义和前面一节在类定义后面再定义default props和props types是一样的效果。但是这样的定义是不是更加的接近静态语言类中定义属性的方式呢?当然之前的default props和props types的定义也可以删去了。

    ES7的方式定义React组件的State

    最后一步就是把initial state(state初始值)从constructor里拿出来放到property initializer(属性初始化器)里。代码如下:

    export default class CartItem extends React.Component {
        state = {
            qty: this.props.initialQty,
            total: 0
        };
    
        constructor(props) {
            super(props);
            // this.state = {
            //     qty: props.initialQty,
            //     total: 0
            // };
        }
    
        //...略...
    }
    

    记得把原来constructor里的state代码删了。

    总结

    通过这篇你就可以熟悉了如何用ES6写React的组件,也熟悉了如何使用ES7的property initializer。

  • 相关阅读:
    201871010113刘兴瑞《面向对象程序设计(java)》第八周学习总结 201871010113
    201871010113刘兴瑞《面向对象程序设计(java)》第六七周学习总结 201871010113
    201871010113刘兴瑞《面向对象程序设计(java)》第十二周学习总结 201871010113
    201871010113刘兴瑞《面向对象程序设计(java)》第七周学习总结 201871010113
    201871010113刘兴瑞《面向对象程序设计(java)》第十一周学习总结 201871010113
    Adobe Brackets 开源、小巧、简洁的代码编辑器
    Pythonopencv摄像头图像捕获
    Linux 系统安全检查(shell)
    zabbix监控历史数据清理
    2、Ansible在使用过程中出现的错误解决方法
  • 原文地址:https://www.cnblogs.com/sunshine-anycall/p/5888190.html
Copyright © 2011-2022 走看看