[项目][准备2] React体验

学习目标

在准备1中,我们利用Bootstrap绘制了一个静态的计算器页面,那个页面没有任何功能。在准备2中,我们将利用React把计算器功能实现。

准备2中不涉及npm相关,准备3中会介绍并使用

学习参考

React版本:15.3.2

可先按以下链接顺序简要学习,重点在跑其中的例子和理解React的思想:

JavaScript相关的内容,可以参考如下链接:

以上链接均来自 菜鸟教程


以下链接内容很值得后续学习:

实践示例

准备工作

目录结构

-prepare2
    -js
        jquery.min.js
        bootstrap.min.js
        react.js
        react-dom.js
        browser.min.js
    -css
        bootstrap.min.css
    index.html

引入依赖

修改index.html的head部分:

<head>
    <title>计算器</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/react.js"></script>
    <script type="text/javascript" src="js/react-dom.js"></script>
    <script type="text/javascript" src="js/browser.min.js"></script>
</head>

组件划分

我们将组件按如下思路划分:

  1. 整个网页应用有一个根组件,App组件
  2. 计算结果显示是一个组件,ResultShow组件
  3. 按钮组应该是一个组件,ButtonContainer组件
  4. 按钮也应该是一个组件,Button组件

组件的树状结构应该是这样的:

-App
    ResultShow
    -ButtonContainer
        Button
        ......
        Button

确定状态

先来思考一下这个计算器是如何工作的的:

  • 计算器能存四个值,一个是运算结果,一个是输入数字,一个是加法标记,一个是运算结束标记
  • 计算器初始运算结果、输入数字为0,加法标记初始为不存在,运算结束标记初始为存在
  • 计算器显示规则:对运算结果操作则显示运算结果,对输入数字操作则显示输入数字,都操作则显示运算结果
  • 计算器工作状态如下:
-数字按钮
    -有加法标记
        数字追加到输入数字
    -无加法标记
        -有运算结束标记 
            数字赋值到运算结果
            清除运算结束标记
        -无运算结束标记 
            数字追加到运算结果

-加法按钮
    -有加法标记
        输入数字+运算结果->运算结果
        输入数字清零
    -无加法标记
        设置加法标记

-等于按钮
    -有加法标记
        输入数字+运算结果->运算结果
        输入数字清零
        清除加法标记
        设置运算结束标记
    -无加法标记
        设置运算结束标记

这个计算器网页应用的状态应该有如下几个:

  • 显示数字应该是一个状态
  • 运算结果应该是一个状态
  • 输入数字应该是一个状态
  • 加法标记应该是一个状态
  • 运算结束应该是一个状态

在这里,5个状态都可以存储在App组件中


组件实现

ResultShow组件:

var ResultShow = React.createClass({
    propTypes: {
        showNumber: React.PropTypes.number.isRequired
    },  
    render: function () {
        return (
            <div className="row clearfix">
                <div className="col-xs-4 column col-xs-offset-8">
                    <center><h3>{this.props.showNumber}</h3></center>
                </div>
            </div>
        );
    }
});

Button组件:

var Button = React.createClass({
    propTypes: {
        buttonType: React.PropTypes.string.isRequired,
        handleOnClick: React.PropTypes.func.isRequired
    },  
    render: function () {
        return (
            <div className="row clearfix">
                <div className="col-xs-12 column">
                    <center><button type="button" className="btn btn-success" onClick={this.props.handleOnClick}>{this.props.buttonType}</button></center>
                </div>
            </div>
        );
    }
});

ButtonContainer组件:

var ButtonContainer = React.createClass({
    propTypes: {
        handleOnClick: React.PropTypes.func.isRequired
    },  
    render: function () {

        var item1 = [];
        var item2 = [];
        var item3 = [];

        for (var i=1; i<=3; i++) {
            item1.push(<Button key={3*i-2+""} handleOnClick={this.props.handleOnClick.bind(null, 3*i-2+"")} buttonType={3*i-2+""} />);
            item2.push(<Button key={3*i-1+""} handleOnClick={this.props.handleOnClick.bind(null, 3*i-1+"")} buttonType={3*i-1+""} />);
            item3.push(<Button key={3*i-0+""} handleOnClick={this.props.handleOnClick.bind(null, 3*i-0+"")} buttonType={3*i-0+""} />);
        }

        item1.push(<Button key={"0"} handleOnClick={this.props.handleOnClick.bind(null, "0")} buttonType={"0"} />);
        item2.push(<Button key={"+"} handleOnClick={this.props.handleOnClick.bind(null, "+")} buttonType={"+"} />);
        item3.push(<Button key={"="} handleOnClick={this.props.handleOnClick.bind(null, "=")} buttonType={"="} />);

        return (
                <div className="row clearfix">
                    <div className="col-xs-4 column">
                        {item1}
                    </div>
                    <div className="col-xs-4 column">
                        {item2}
                    </div>
                    <div className="col-xs-4 column">
                        {item3}
                    </div>
                </div>
                );
    }
});

App组件:

var App = React.createClass({
    getInitialState: function () {
        return {    
                showNumber: 0, 
                resultNumber : 0, 
                inputNumber: 0, 
                addFlag: false, 
                endFlag: true
                };
    },
    handleOnClick: function(buttonType, event) {
        switch (buttonType) {
            case '+' :
                if (this.state.addFlag) {
                    this.setState({
                        resultNumber: this.state.resultNumber + this.state.inputNumber,
                        inputNumber: 0,
                        showNumber: this.state.resultNumber + this.state.inputNumber //new resultNumber
                    });
                } else {
                    this.setState({
                        addFlag: true
                    });
                }
                break;
            case '=' :
                if (this.state.addFlag) {
                    this.setState({
                        resultNumber: this.state.resultNumber + this.state.inputNumber,
                        inputNumber: 0,
                        addFlag: false,
                        endFlag: true,
                        showNumber: this.state.resultNumber + this.state.inputNumber //new resultNumber
                    });
                } else {
                    this.setState({
                        endFlag: true
                    });
                }
                break;
            default:
                if (this.state.addFlag) {
                    this.setState({
                        inputNumber: this.state.inputNumber*10 + parseInt(buttonType),
                        showNumber: this.state.inputNumber*10 + parseInt(buttonType) //new inputNumber
                    });
                } else {
                    if (this.state.endFlag) {
                        this.setState({
                            resultNumber: parseInt(buttonType),
                            endFlag: false,
                            showNumber: parseInt(buttonType) //new resultNumber
                        });
                    } else {
                        this.setState({
                            resultNumber: this.state.resultNumber*10 + parseInt(buttonType),
                            showNumber: this.state.resultNumber*10 + parseInt(buttonType) //new resultNumber
                        });
                    }
                }
                break;
        }
    },
    render: function () {
        return (
            <div className="container">
                <div className="row clearfix">
                    <div className="col-xs-12 column">
                        <div className="row clearfix">
                            <div className="col-xs-6 column col-xs-offset-3">
                                <div className="jumbotron">
                                    <div className="pull-left">
                                        <h1><strong>计算器</strong></h1>
                                    </div>
                                    <p></p>
                                    <div className="row clearfix">
                                        <div className="col-xs-12 column">
                                            <ResultShow showNumber={this.state.showNumber} />
                                            <p></p>
                                            <ButtonContainer handleOnClick={this.handleOnClick} />
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
});

全部代码

index.html的全部代码,配合上文的目录结构,本地直接用浏览器打开就可以看到效果:

<!DOCTYPE html>
<html>
<head>
    <title>计算器</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/react.js"></script>
    <script type="text/javascript" src="js/react-dom.js"></script>
    <script type="text/javascript" src="js/browser.min.js"></script>
</head>
<body>
    <div id="app">
    </div>

    <script type="text/babel">
        var ResultShow = React.createClass({
            propTypes: {
                showNumber: React.PropTypes.number.isRequired
            },  
            render: function () {
                return (
                    <div className="row clearfix">
                        <div className="col-xs-4 column col-xs-offset-8">
                            <center><h3>{this.props.showNumber}</h3></center>
                        </div>
                    </div>
                );
            }
        });


        var Button = React.createClass({
            propTypes: {
                buttonType: React.PropTypes.string.isRequired,
                handleOnClick: React.PropTypes.func.isRequired
            },  
            render: function () {
                return (
                    <div className="row clearfix">
                        <div className="col-xs-12 column">
                            <center><button type="button" className="btn btn-success" onClick={this.props.handleOnClick}>{this.props.buttonType}</button></center>
                        </div>
                    </div>
                );
            }
        });


        var ButtonContainer = React.createClass({
            propTypes: {
                handleOnClick: React.PropTypes.func.isRequired
            },  
            render: function () {

                var item1 = [];
                var item2 = [];
                var item3 = [];

                for (var i=1; i<=3; i++) {
                    item1.push(<Button key={3*i-2+""} handleOnClick={this.props.handleOnClick.bind(null, 3*i-2+"")} buttonType={3*i-2+""} />);
                    item2.push(<Button key={3*i-1+""} handleOnClick={this.props.handleOnClick.bind(null, 3*i-1+"")} buttonType={3*i-1+""} />);
                    item3.push(<Button key={3*i-0+""} handleOnClick={this.props.handleOnClick.bind(null, 3*i-0+"")} buttonType={3*i-0+""} />);
                }

                item1.push(<Button key={"0"} handleOnClick={this.props.handleOnClick.bind(null, "0")} buttonType={"0"} />);
                item2.push(<Button key={"+"} handleOnClick={this.props.handleOnClick.bind(null, "+")} buttonType={"+"} />);
                item3.push(<Button key={"="} handleOnClick={this.props.handleOnClick.bind(null, "=")} buttonType={"="} />);

                return (
                        <div className="row clearfix">
                            <div className="col-xs-4 column">
                                {item1}
                            </div>
                            <div className="col-xs-4 column">
                                {item2}
                            </div>
                            <div className="col-xs-4 column">
                                {item3}
                            </div>
                        </div>
                        );
            }
        });


        var App = React.createClass({
            getInitialState: function () {
                return {    
                        showNumber: 0, 
                        resultNumber : 0, 
                        inputNumber: 0, 
                        addFlag: false, 
                        endFlag: true
                        };
            },
            handleOnClick: function(buttonType, event) {
                switch (buttonType) {
                    case '+' :
                        if (this.state.addFlag) {
                            this.setState({
                                resultNumber: this.state.resultNumber + this.state.inputNumber,
                                inputNumber: 0,
                                showNumber: this.state.resultNumber + this.state.inputNumber //new resultNumber
                            });
                        } else {
                            this.setState({
                                addFlag: true
                            });
                        }
                        break;
                    case '=' :
                        if (this.state.addFlag) {
                            this.setState({
                                resultNumber: this.state.resultNumber + this.state.inputNumber,
                                inputNumber: 0,
                                addFlag: false,
                                endFlag: true,
                                showNumber: this.state.resultNumber + this.state.inputNumber //new resultNumber
                            });
                        } else {
                            this.setState({
                                endFlag: true
                            });
                        }
                        break;
                    default:
                        if (this.state.addFlag) {
                            this.setState({
                                inputNumber: this.state.inputNumber*10 + parseInt(buttonType),
                                showNumber: this.state.inputNumber*10 + parseInt(buttonType) //new inputNumber
                            });
                        } else {
                            if (this.state.endFlag) {
                                this.setState({
                                    resultNumber: parseInt(buttonType),
                                    endFlag: false,
                                    showNumber: parseInt(buttonType) //new resultNumber
                                });
                            } else {
                                this.setState({
                                    resultNumber: this.state.resultNumber*10 + parseInt(buttonType),
                                    showNumber: this.state.resultNumber*10 + parseInt(buttonType) //new resultNumber
                                });
                            }
                        }
                        break;
                }
            },
            render: function () {
                return (
                    <div className="container">
                        <div className="row clearfix">
                            <div className="col-xs-12 column">
                                <div className="row clearfix">
                                    <div className="col-xs-6 column col-xs-offset-3">
                                        <div className="jumbotron">
                                            <div className="pull-left">
                                                <h1><strong>计算器</strong></h1>
                                            </div>
                                            <p></p>
                                            <div className="row clearfix">
                                                <div className="col-xs-12 column">
                                                    <ResultShow showNumber={this.state.showNumber} />
                                                    <p></p>
                                                    <ButtonContainer handleOnClick={this.handleOnClick} />
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                );
            }
        });


        ReactDOM.render(
            <App />,
            document.getElementById('app')
        );
    </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值