zoukankan      html  css  js  c++  java
  • React问答小demo

    在学习react初期,看了一些视频和资料,react基础知识差不多学完,跟着网上的一个教程,做了一个小型的问答demo。

    需求看图说:

    1.点击“添加”按钮,显示问题输入表单,再次点击,隐藏表单。同时,点击“取消”按钮,隐藏表单。

    2.输入问题标题和内容后,点击“确认”按钮,将问题显示在下方(按照投票数从高到低)。

    3.每个问题有加票和减票功能,在点击的同时,将问题按照投票数从高到低排序。

    实现过程:

    一、开发环境和工具

    1.npm init (生成package.json文件) (按照向导填写各个字段,最后生成 package.json 文件。

    容易出错的是: name的值不要和包包同名 。

    比如我们后续需要使用npm安装几个包包:browserify react reactify ...则name值如果写作“browserify”或“react”,此依赖会安装失败!

    提示如下:

    npm WARN install Refusing to install react as a dependency of itself)

    2.npm install react --save        npm install react-dom --save (最开始就是没有安装react-dom,所以一直渲染不出来)

    3.npm install -g gulp

    4.npm install --save-dev gulp gulp-browserify gulp-concat gulp-react gulp-connect lodash reactify

    (这里注意一下,npm install --save 与 npm install --save-dev 的区别,一个放在package.json 的dependencies , 一个放在devDependencies里面,产品模式用dependencies,开发模式用devDep。)

    5.bower init (生成bower.json文件)

    6.bower install bootstrap --save

    7.新建app文件夹,再在下面建一个js文件夹,创建main.js

    8.新建dist文件(压缩后的文件放的地方)

    9.创建gulpfile.js

    二、代码开发

    gulpfile.js内容如下:

     1 var gulp = require('gulp'),
     2     connect = require('gulp-connect'),
     3     browserify = require('gulp-browserify'),
     4     concat = require('gulp-concat'),
     5     port = process.env.port || 5000;
     6 
     7 gulp.task('browserify',function(){
     8     gulp.src('./app/js/main.js')
     9         .pipe(browserify({
    10             transform: 'reactify',
    11         }))
    12         .pipe(gulp.dest('./dist/js'))
    13 });
    14 
    15 // live reload
    16 gulp.task('connect',function(){
    17     connect.server({
    18         // root:'./',
    19         port: port,
    20         livereload: true
    21     })
    22 })
    23 
    24 // reload Js
    25 gulp.task('js',function(){
    26     gulp.src('./dist/**/*.js')
    27         .pipe( connect.reload() )
    28 })
    29 
    30 gulp.task('html',function(){
    31     gulp.src('./app/**/*.html')
    32         .pipe( connect.reload() )
    33 });
    34 
    35 gulp.task('watch',function(){
    36     gulp.watch('./dist/**/*.js',['js']);
    37     gulp.watch('./app/**/*.html',['html']);
    38     gulp.watch('./app/js/**/*.js',['browserify']);
    39 })
    40 
    41 gulp.task('default',['browserify']);
    42 
    43 gulp.task('serve',['browserify','connect','watch']);

    静态页面html:

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4     <meta charset="utf8">
     5     <title>React问答 app </title>
     6     <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
     7     <style>
     8         .container{
     9             max-width: 800px;
    10         }
    11         .jumbotron .container{
    12             position: relative;
    13             max-width: 800px;
    14         }
    15         #add-question-btn{
    16             position: absolute;
    17             bottom: -20px;
    18             right: 20px;
    19         }
    20         form[name="addQuestion"] .btn{
    21             margin: 20px 0 0 15px;
    22         }
    23         .media-left{
    24             text-align: center;
    25             width:70px;
    26             float: left;
    27         }
    28         .media-left .btn{
    29             margin-bottom: 10px;
    30         }
    31         .vote-count{
    32             display: block;
    33         }
    34     </style>
    35 </head>
    36 <body>
    37 <div id="app">
    38     <div class="jumbotron text-center">
    39         <div class="container">
    40             <h1>React问答</h1>
    41             <button id="add-question-btn" class="btn btn-success">添加问题</button>
    42         </div>
    43     </div>
    44     <div class="main container">
    45         <form name="addQuestion" class="clearfix">
    46             <div class="form-group">
    47                 <label for="qtitle">问题</label>
    48                 <input type="text" class="form-control" id="qtitle" placeholder="您的问题的标题">
    49             </div>
    50             <textarea class="form-control" rows="3" placeholder="问题的描述"></textarea>
    51             <button class="btn btn-success pull-right">确认</button>
    52             <button class="btn btn-default pull-right">取消</button>
    53         </form>
    54         <div id="questions" class="">
    55             <div class="media">
    56                 <div class="media-left">
    57                     <button class="btn btn-default">
    58                         <span class="glyphicon glyphicon-chevron-up"></span>
    59                         <span class="vote-count">22</span>
    60                     </button>
    61                     <button class="btn btn-default">
    62                         <span class="glyphicon glyphicon-chevron-down"></span>
    63                     </button>
    64                 </div>
    65                 <div class="media-body">
    66                     <h4 class="media-heading">产品经理与程序员矛盾的本质是什么?</h4>
    67                     <p>理性探讨,请勿撕逼。产品经理的主要工作职责是产品设计。接受来自其他部门的需求,经过设计后交付研发。但这里有好些职责不清楚的地方。</p>
    68                 </div>
    69             </div>
    70 
    71             <div class="media">
    72                 <div class="media-left">
    73                     <button class="btn btn-default">
    74                         <span class="glyphicon glyphicon-chevron-up"></span>
    75                         <span class="vote-count">12</span>
    76                     </button>
    77                     <button class="btn btn-default">
    78                         <span class="glyphicon glyphicon-chevron-down"></span>
    79                     </button>
    80                 </div>
    81                 <div class="media-body">
    82                     <h4 class="media-heading">热爱编程是一种怎样的体验?</h4>
    83                     <p>别人对玩游戏感兴趣,我对写代码、看技术文章感兴趣;把泡github、stackoverflow、v2ex、reddit、csdn当做是兴趣爱好;遇到重复的工作,总想着能不能通过程序实现自动化;喝酒的时候把写代码当下酒菜,边喝边想边敲;不给工资我也会来加班;做梦都在写代码。</p>
    84                 </div>
    85             </div>
    86 
    87         </div>
    88 
    89     </div>
    90 </div>
    91 
    92 <!--
    93 <script src="/dist/js/main.js"></script>  -->
    94 </body>
    95 </html>

    接下来的react代码转化,我就不详细谢了,在这里贴出我的项目文件展示:

    index.html

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4     <meta charset="utf8">
     5     <title>React问答 app </title>
     6     <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
     7     <style>
     8         .container{
     9             max-width: 800px;
    10         }
    11         .jumbotron .container{
    12             position: relative;
    13             max-width: 800px;
    14         }
    15         #add-question-btn{
    16             position: absolute;
    17             bottom: -20px;
    18             right: 20px;
    19         }
    20         form[name="addQuestion"] .btn{
    21             margin: 20px 0 0 15px;
    22         }
    23         .media-left{
    24             text-align: center;
    25             width:70px;
    26             float: left;
    27         }
    28         .media-left .btn{
    29             margin-bottom: 10px;
    30         }
    31         .vote-count{
    32             display: block;
    33         }
    34     </style>
    35 </head>
    36 <body>
    37 <div id="app"> </div>
    38 
    39 <script src="/dist/js/main.js"></script>
    40 
    41 </body>
    42 </html>

    main.js

    1 var React = require('react');
    2 var ReactDOM = require('react-dom');
    3 var QuestionApp = require('./components/QuestionApp.js');
    4 /* 模块名可使用相对路径(以./开头),或者是绝对路径(以/或C:之类的盘符开头)*/
    5 
    6 var mainCom = ReactDOM.render(
    7     <QuestionApp />,
    8     document.getElementById('app')
    9 );

    QuestionApp.js

     1 var React = require('react');
     2 var ShowAddBtn = require('./ShowAddBtn.js');
     3 var QuestionForm = require('./QuestionForm.js');
     4 var QuestionList = require('./QuestionList.js');
     5 module.exports = React.createClass({
     6     getInitialState: function(){
     7         var questions = [
     8             {
     9                 key: 1,
    10                 title: '产品经理与程序员矛盾的本质是什么?',
    11                 description: '理性探讨,请勿撕逼。产品经理的主要工作职责是产品设计。接受来自其他部门的需求,经过设计后交付研发。但这里有好些职责不清楚的地方。',
    12                 voteCount: 2
    13             },
    14             {
    15                 key: 2,
    16                 title: '热爱编程是一种怎样的体验?',
    17                 description: '别人对玩游戏感兴趣,我对写代码、看技术文章感兴趣;把泡github、stackoverflow、v2ex、reddit、csdn当做是兴趣爱好;遇到重复的工作,总想着能不能通过程序实现自动化;喝酒的时候把写代码当下酒菜,边喝边想边敲;不给工资我也会来加班;做梦都在写代码。',
    18                 voteCount: 3
    19             }
    20         ];
    21         questions = this.questionSort(questions); //sort the init questions
    22         return {
    23             displayForm: false,
    24             questions: questions
    25         };
    26     },
    27     onToggleForm: function(){
    28         this.setState({
    29             displayForm: !this.state.displayForm
    30         });
    31     },
    32     onQuestionNew: function(newQuestion){
    33         newQuestion.key = this.state.questions.length + 1;
    34         var newQuestions = this.state.questions.concat(newQuestion);
    35         newQuestions = this.questionSort(newQuestions);
    36         this.setState({
    37             questions: newQuestions
    38         });
    39     },
    40     questionSort: function(questions){
    41         questions.sort(function(a,b){
    42             return b.voteCount - a.voteCount;
    43         });
    44         return questions;//之前一直报错,这里忘记return
    45     },
    46     onVote: function(nowKey, newVoteCount){
    47         var questions = this.state.questions;
    48         var index = 0;
    49         for(var i=0; i<questions.length; i++){
    50             if(questions[i].key == nowKey){
    51                 index = i;
    52             }
    53         }
    54         questions[index].voteCount = newVoteCount;
    55         questions = this.questionSort(questions);
    56         this.setState({
    57             questions: questions
    58         });
    59     },
    60     render: function(){
    61         return (
    62             <div>
    63                 <div className="jumbotron text-center">
    64                     <div className="container">
    65                         <h1>React问答</h1>
    66                         <ShowAddBtn onToggleForm={this.onToggleForm}/>
    67                     </div>
    68                 </div>
    69                 <div className="main container">
    70                     <QuestionForm onQuestionNew={this.onQuestionNew} displayForm={this.state.displayForm} onToggleForm={this.onToggleForm}/>
    71                     <QuestionList onVote={this.onVote} questions={this.state.questions}/>
    72                 </div>
    73             </div>
    74         )
    75     }
    76 });

    ShowAddBtn.js

    1 var React = require('react');
    2 module.exports = React.createClass({
    3     render: function(){
    4         return (
    5             <button id="add-question-btn" className="btn btn-success" onClick={this.props.onToggleForm}>添加问题</button>
    6         )
    7     }
    8 });

    QuestionForm.js

     1 var React = require('react');
     2 module.exports = React.createClass({
     3     handleSubmit: function(e){
     4         e.preventDefault();
     5         var newQuestion = {
     6             title: this.refs.title.value,
     7             description: this.refs.description.value,
     8             voteCount: 0
     9         };
    10         this.refs.questionForm.reset();
    11         this.props.onQuestionNew(newQuestion);
    12     },
    13     render: function(){
    14         return (
    15             <form name="addQuestion" className="clearfix" ref="questionForm"
    16                   style={{display: this.props.displayForm ? 'block' : 'none'}}
    17                   onSubmit={this.handleSubmit}>
    18                 <div className="form-group">
    19                     <label htmlFor="qtitle">问题</label>
    20                     <input ref="title" type="text" className="form-control" id="qtitle" placeholder="您的问题的标题"/>
    21                 </div>
    22                 <textarea ref="description" className="form-control" rows="3" placeholder="问题的描述"></textarea>
    23                 <button className="btn btn-success pull-right">确认</button>
    24                 <a className="btn btn-default pull-right" onClick={this.props.onToggleForm}>取消</a>
    25             </form>
    26         )
    27     }
    28 });

    QuestionList.js

     1 var React = require('react');
     2 var QuestionItem = require('./QuestionItem.js');
     3 module.exports = React.createClass({
     4     render: function(){
     5         var questions = this.props.questions;
     6         var _this = this;//这里的this要单独保存,否则下面的map中的this指的是循环的每个对象
     7         var questionComps = questions.map(function(qst){
     8             return <QuestionItem
     9                 key={qst.key}
    10                 questionKey={qst.key}
    11                 title={qst.title}
    12                 description={qst.description}
    13                 voteCount={qst.voteCount}
    14                 onVote={_this.props.onVote}/>
    15         });
    16         //开始一直报错,是因为这里,render里面,return(), 没有写最外层div
    17         return (
    18             <div id="questions" className="">
    19                 {questionComps}/*直接放个数组在这里,他会自动去循环*/
    20             </div>
    21         )
    22     }
    23 });

    QuestionItem.js

     1 var React = require('react');
     2 module.exports = React.createClass({
     3     voteUp: function(){
     4         var newVoteCount = parseInt(this.props.voteCount, 10) + 1;
     5         //this.props.questionKey这里必须重
     6         // 新定义一个questionKey属性, 不能this.props.key
     7         this.props.onVote(this.props.questionKey, newVoteCount);
     8     },
     9     voteDown: function(){
    10         var newVoteCount = parseInt(this.props.voteCount, 10) - 1;
    11         this.props.onVote(this.props.questionKey, newVoteCount);
    12     },
    13     render: function(){
    14         return (
    15             <div className="media">
    16                 <div className="media-left">
    17                     <button className="btn btn-default" onClick={this.voteUp}>
    18                         <span className="glyphicon glyphicon-chevron-up"></span>
    19                         <span className="vote-count">{this.props.voteCount}</span>
    20                     </button>
    21                     <button className="btn btn-default" onClick={this.voteDown}>
    22                         <span className="glyphicon glyphicon-chevron-down"></span>
    23                     </button>
    24                 </div>
    25                 <div className="media-body">
    26                     <h4 className="media-heading">{this.props.title}</h4>
    27                     <p>{this.props.description}</p>
    28                 </div>
    29             </div>
    30         )
    31     }
    32 
    33 });

    到这里,所有代码就完成了,在命令行里面执行gulp serve命令,然后在浏览器中访问localhost:5000。

    到此整个小demo就算完成了。对于react-router, react redux等深入知识点还在进一步学习过程中,欢迎大家提出问题,一起讨论。

  • 相关阅读:
    [a0004] <创作> 随笔视图索引
    [a0003] <创作> 全局视图索引
    git提交时忽略指定文件
    解决:gradle 前言中不允许有内容
    【LINQ标准查询操作符总结】之聚合操符
    RxJS 中的创建操作符
    项目管理(1) 什么是项目?
    数据库表数据统计及数据表的数据大小统计SQL
    C# 中一些类关系的判定方法
    Windows Azure NotificationHub+Firebase Cloud Message 实现消息推动(付源码)
  • 原文地址:https://www.cnblogs.com/xiayu25/p/6081507.html
Copyright © 2011-2022 走看看