在学习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内容如下:

 var gulp = require('gulp'),
connect = require('gulp-connect'),
browserify = require('gulp-browserify'),
concat = require('gulp-concat'),
port = process.env.port || 5000; gulp.task('browserify',function(){
gulp.src('./app/js/main.js')
.pipe(browserify({
transform: 'reactify',
}))
.pipe(gulp.dest('./dist/js'))
}); // live reload
gulp.task('connect',function(){
connect.server({
// root:'./',
port: port,
livereload: true
})
}) // reload Js
gulp.task('js',function(){
gulp.src('./dist/**/*.js')
.pipe( connect.reload() )
}) gulp.task('html',function(){
gulp.src('./app/**/*.html')
.pipe( connect.reload() )
}); gulp.task('watch',function(){
gulp.watch('./dist/**/*.js',['js']);
gulp.watch('./app/**/*.html',['html']);
gulp.watch('./app/js/**/*.js',['browserify']);
}) gulp.task('default',['browserify']); gulp.task('serve',['browserify','connect','watch']);

静态页面html:

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title>React问答 app </title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<style>
.container{
max-width: 800px;
}
.jumbotron .container{
position: relative;
max-width: 800px;
}
#add-question-btn{
position: absolute;
bottom: -20px;
right: 20px;
}
form[name="addQuestion"] .btn{
margin: 20px 0 0 15px;
}
.media-left{
text-align: center;
width:70px;
float: left;
}
.media-left .btn{
margin-bottom: 10px;
}
.vote-count{
display: block;
}
</style>
</head>
<body>
<div id="app">
<div class="jumbotron text-center">
<div class="container">
<h1>React问答</h1>
<button id="add-question-btn" class="btn btn-success">添加问题</button>
</div>
</div>
<div class="main container">
<form name="addQuestion" class="clearfix">
<div class="form-group">
<label for="qtitle">问题</label>
<input type="text" class="form-control" id="qtitle" placeholder="您的问题的标题">
</div>
<textarea class="form-control" rows="3" placeholder="问题的描述"></textarea>
<button class="btn btn-success pull-right">确认</button>
<button class="btn btn-default pull-right">取消</button>
</form>
<div id="questions" class="">
<div class="media">
<div class="media-left">
<button class="btn btn-default">
<span class="glyphicon glyphicon-chevron-up"></span>
<span class="vote-count">22</span>
</button>
<button class="btn btn-default">
<span class="glyphicon glyphicon-chevron-down"></span>
</button>
</div>
<div class="media-body">
<h4 class="media-heading">产品经理与程序员矛盾的本质是什么?</h4>
<p>理性探讨,请勿撕逼。产品经理的主要工作职责是产品设计。接受来自其他部门的需求,经过设计后交付研发。但这里有好些职责不清楚的地方。</p>
</div>
</div> <div class="media">
<div class="media-left">
<button class="btn btn-default">
<span class="glyphicon glyphicon-chevron-up"></span>
<span class="vote-count">12</span>
</button>
<button class="btn btn-default">
<span class="glyphicon glyphicon-chevron-down"></span>
</button>
</div>
<div class="media-body">
<h4 class="media-heading">热爱编程是一种怎样的体验?</h4>
<p>别人对玩游戏感兴趣,我对写代码、看技术文章感兴趣;把泡github、stackoverflow、v2ex、reddit、csdn当做是兴趣爱好;遇到重复的工作,总想着能不能通过程序实现自动化;喝酒的时候把写代码当下酒菜,边喝边想边敲;不给工资我也会来加班;做梦都在写代码。</p>
</div>
</div> </div> </div>
</div> <!--
<script src="/dist/js/main.js"></script> -->
</body>
</html>

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

index.html

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title>React问答 app </title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<style>
.container{
max-width: 800px;
}
.jumbotron .container{
position: relative;
max-width: 800px;
}
#add-question-btn{
position: absolute;
bottom: -20px;
right: 20px;
}
form[name="addQuestion"] .btn{
margin: 20px 0 0 15px;
}
.media-left{
text-align: center;
width:70px;
float: left;
}
.media-left .btn{
margin-bottom: 10px;
}
.vote-count{
display: block;
}
</style>
</head>
<body>
<div id="app"> </div> <script src="/dist/js/main.js"></script> </body>
</html>

main.js

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

QuestionApp.js

 var React = require('react');
var ShowAddBtn = require('./ShowAddBtn.js');
var QuestionForm = require('./QuestionForm.js');
var QuestionList = require('./QuestionList.js');
module.exports = React.createClass({
getInitialState: function(){
var questions = [
{
key: 1,
title: '产品经理与程序员矛盾的本质是什么?',
description: '理性探讨,请勿撕逼。产品经理的主要工作职责是产品设计。接受来自其他部门的需求,经过设计后交付研发。但这里有好些职责不清楚的地方。',
voteCount: 2
},
{
key: 2,
title: '热爱编程是一种怎样的体验?',
description: '别人对玩游戏感兴趣,我对写代码、看技术文章感兴趣;把泡github、stackoverflow、v2ex、reddit、csdn当做是兴趣爱好;遇到重复的工作,总想着能不能通过程序实现自动化;喝酒的时候把写代码当下酒菜,边喝边想边敲;不给工资我也会来加班;做梦都在写代码。',
voteCount: 3
}
];
questions = this.questionSort(questions); //sort the init questions
return {
displayForm: false,
questions: questions
};
},
onToggleForm: function(){
this.setState({
displayForm: !this.state.displayForm
});
},
onQuestionNew: function(newQuestion){
newQuestion.key = this.state.questions.length + 1;
var newQuestions = this.state.questions.concat(newQuestion);
newQuestions = this.questionSort(newQuestions);
this.setState({
questions: newQuestions
});
},
questionSort: function(questions){
questions.sort(function(a,b){
return b.voteCount - a.voteCount;
});
return questions;//之前一直报错,这里忘记return
},
onVote: function(nowKey, newVoteCount){
var questions = this.state.questions;
var index = 0;
for(var i=0; i<questions.length; i++){
if(questions[i].key == nowKey){
index = i;
}
}
questions[index].voteCount = newVoteCount;
questions = this.questionSort(questions);
this.setState({
questions: questions
});
},
render: function(){
return (
<div>
<div className="jumbotron text-center">
<div className="container">
<h1>React问答</h1>
<ShowAddBtn onToggleForm={this.onToggleForm}/>
</div>
</div>
<div className="main container">
<QuestionForm onQuestionNew={this.onQuestionNew} displayForm={this.state.displayForm} onToggleForm={this.onToggleForm}/>
<QuestionList onVote={this.onVote} questions={this.state.questions}/>
</div>
</div>
)
}
});

ShowAddBtn.js

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

QuestionForm.js

 var React = require('react');
module.exports = React.createClass({
handleSubmit: function(e){
e.preventDefault();
var newQuestion = {
title: this.refs.title.value,
description: this.refs.description.value,
voteCount: 0
};
this.refs.questionForm.reset();
this.props.onQuestionNew(newQuestion);
},
render: function(){
return (
<form name="addQuestion" className="clearfix" ref="questionForm"
style={{display: this.props.displayForm ? 'block' : 'none'}}
onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="qtitle">问题</label>
<input ref="title" type="text" className="form-control" id="qtitle" placeholder="您的问题的标题"/>
</div>
<textarea ref="description" className="form-control" rows="3" placeholder="问题的描述"></textarea>
<button className="btn btn-success pull-right">确认</button>
<a className="btn btn-default pull-right" onClick={this.props.onToggleForm}>取消</a>
</form>
)
}
});

QuestionList.js

 var React = require('react');
var QuestionItem = require('./QuestionItem.js');
module.exports = React.createClass({
render: function(){
var questions = this.props.questions;
var _this = this;//这里的this要单独保存,否则下面的map中的this指的是循环的每个对象
var questionComps = questions.map(function(qst){
return <QuestionItem
key={qst.key}
questionKey={qst.key}
title={qst.title}
description={qst.description}
voteCount={qst.voteCount}
onVote={_this.props.onVote}/>
});
//开始一直报错,是因为这里,render里面,return(), 没有写最外层div
return (
<div id="questions" className="">
{questionComps}/*直接放个数组在这里,他会自动去循环*/
</div>
)
}
});

QuestionItem.js

 var React = require('react');
module.exports = React.createClass({
voteUp: function(){
var newVoteCount = parseInt(this.props.voteCount, 10) + 1;
//this.props.questionKey这里必须重
// 新定义一个questionKey属性, 不能this.props.key
this.props.onVote(this.props.questionKey, newVoteCount);
},
voteDown: function(){
var newVoteCount = parseInt(this.props.voteCount, 10) - 1;
this.props.onVote(this.props.questionKey, newVoteCount);
},
render: function(){
return (
<div className="media">
<div className="media-left">
<button className="btn btn-default" onClick={this.voteUp}>
<span className="glyphicon glyphicon-chevron-up"></span>
<span className="vote-count">{this.props.voteCount}</span>
</button>
<button className="btn btn-default" onClick={this.voteDown}>
<span className="glyphicon glyphicon-chevron-down"></span>
</button>
</div>
<div className="media-body">
<h4 className="media-heading">{this.props.title}</h4>
<p>{this.props.description}</p>
</div>
</div>
)
} });

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

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

React问答小demo的更多相关文章

  1. 助你了解react的小demo

    React是个啥 React 是一个用于构建用户界面的 JAVASCRIPT 库. React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图). React 起源于 Facebo ...

  2. MobX+react使用小demo

    第一次接触mobx,网上找了很多例子,写此主要总结一下create-react-app + mobx入门 create-react-app myreact cd myreact npm install ...

  3. 学习react,动手实现一个小demo(仿知乎问答)

    学习react也有一周的时间,最近自己做了个仿知乎问答的小demo,项目源码在github上:https://github.com/yang302/reactQa 使用技术:bower+gulp+re ...

  4. swiper嵌套小demo(移动端触摸滑动插件)

    swiper(移动端触摸滑动插件) tip:自己敲得Swiper 的小demo,可以复制粘贴看看效果哦. swiper的js包css包下链接地址 :  https://github.com/Clear ...

  5. React Native八大Demo

    参考资料:http://www.cnblogs.com/shaoting/p/7148240.html 下一个项目公司也打算使用react native.大致看了下原型设计,写几个小demo先试试水. ...

  6. 新手 gulp+ seajs 小demo

    首先,不说废话,它的介绍和作者就不在多说了,网上一百度一大堆: 我在这里只是来写写我这2天抽空对seajs的了解并爬过的坑,和实现的一个小demo(纯属为了实现,高手请绕道); 一.环境工具及安装 1 ...

  7. Nancy之基于Nancy.Hosting.Self的小Demo

    继昨天的Nancy之基于Nancy.Hosting.Aspnet的小Demo后, 今天来做个基于Nancy.Hosting.Self的小Demo. 关于Self Hosting Nancy,官方文档的 ...

  8. Nancy之基于Nancy.Owin的小Demo

    前面做了基于Nancy.Hosting.Aspnet和Nancy.Hosting.Self的小Demo 今天我们来做个基于Nancy.Owin的小Demo 开始之前我们来说说什么是Owin和Katan ...

  9. Nancy之基于Self Hosting的补充小Demo

    前面把Hosting Nancy with ASP.NET.Self Hosting Nancy和Hosting Nancy with OWIN 以demo的形式简单描述了一下. 这篇是为Self H ...

随机推荐

  1. 使用nice命令调整进程优先级

    Adjusting Process Priority with nice   When Linux processes are started, they are started with a spe ...

  2. Environment Configuration Files

    Environment Configuration Files When a user logs in, an environment is created for that user automat ...

  3. css书写步骤

    CSS整体书写步骤1:CSS RESET 重置2:CSS GLABAL 全局属性3: CSS分模块属性,(先写默认样式和设计图相差最大的部分,先大块布局,后细致调整) <style>/*C ...

  4. mysql limit性能问题

    offset大的时候的比较 1. SELECT * FROM persons LIMIT 200000,10; 耗时0.109s 2. SELECT *FROM persons WHERE id> ...

  5. Android学习笔记:如何设置ImageView中图片的显示方式

    我们在用ImageView显示图片时,很多情况下图片的大小与ImageView的尺寸不是完全一样的.这时就涉及到该如何设置显示图片了. ImageView有个重要的属性是ScaleType,该属性用以 ...

  6. 网络编程 socket-实例

    1.设计界面:   2.效果界面:   3.具体实现代码:   public partial class frmMain : Form { public frmMain() { InitializeC ...

  7. JDBC使用sql语句

    JDBC---连接数据库 java与数据库连接需要驱动,这个驱动则是JDBC,连接的时候需要ip+端口号+dbname 还要用户名和密码 改java文件的编码方式--在项目名点右键属性----把编码方 ...

  8. 学习OpenSeadragon之一(一个显示多层图片的开源JS库)

    OpenSeadragon是一个可以显示多层图片(可放大缩小)的Web库,基于JavaScript,支持桌面和手机. 由于我项目需要,却没有找到任何中文教程,因此在官网上一边学习,一边总结于此. 官网 ...

  9. 狗狗40题~ (Volume C)

    A - Triangles 记忆化搜索呗.搜索以某三角形为顶的最大面积,注意边界情况. #include <stdio.h> #include <cstring> #inclu ...

  10. 狗狗40题~(Volume A)

    A - The Willy Memorial Program 大模拟题…… 一开始的思路不对,修修补补WA了十发.当时想直接一个并查集做连通来搞定它,结果发现不能很好地判断各管的水位.究其原因还是因为 ...