React.js入门笔记(再续):评论框的实现
本案例来自React.js中文官网对应内容。
一. 运行环境
<link rel="stylesheet" type="text/css" href="css/css.css"/>
<!-- 核心 -->
<script src="js/react.js"></script>
<!-- 加载dom方法 -->
<script src="js/react-dom.js"></script>
<!-- 将 JSX 语法转为 JavaScript 语法 -->
<script src="js/browser.min.js"></script>
<!-- jquery -->
<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
<!--markdown渲染引擎-->
<script type="text/javascript" src="js/remarkable.min.js"></script>
<!-- 自身的javascript代码 -->
<script type="text/javascript" src="js/js.js"></script>
</head>
二. 组件架构
App下有两个子组件CommentList(评论列表)和CommentForm(评论区),其中CommentList下又有一个子组件Comment(评论)
- App
- CommentList
- Comment
- CommentForm
Comment包括一个h2的评论人名称,一个span的评论内容,获取数据之后,Comment组件以数组的形式传入CommentList。
三. 流动数据
接下来就是把这5个组件写出来。
// 最底层的组件Comment,隶属于CommentList
var Comment=React.createClass({
render:function(){
return (
);
}
});
// 中层对象,包括CommentList和CommentForm
var CommentList=React.createClass({
render:function(){
return (
);
}
});
var CommentForm=React.createClass({
render:function(){
return (
);
}
});
// 最高层对象App,包括两个中层组件
var App=React.createClass({
render:function(){
return (
);
}
});
// 渲染模块
ReactDOM.render(
<App/>,
document.getElementById('example')
);
数据通过props传入App,可以在html文件根目录下创建一个“json.json”文件:放入以下内容:
[
{"id": 1, "author": "小明", "text": "小明摸摸大"},
{"id": 2, "author": "小红", "text": "小红萌萌哒"}
]
所以我只要给App传递一个url即可。然后在文档插入之后执行jQuery的getJSON方法:最后在存入到App的state中。每次更新state,对会造成变化。
既然state可以实时更新,那么不如设置一个定时器,每隔2s执行一次数据刷新。刷新间隔由App的props.timer传入。
目前的组件变成了这样
// 最底层的组件Comment,隶属于CommentList
var Comment=React.createClass({
render:function(){
return (
<li>
<h2>{this.props.author}</h2>
<span>{this.props.text}</span>
</li>
);
}
});
//
// 中层对象,包括CommentList和CommentForm
var CommentForm=React.createClass({
render:function(){
//console.log(this.props)
return (
<div></div>
);
}
});
var CommentList=React.createClass({
render:function(){
var arr=[];
this.props.data.map(function(item){
//console.log(item.author)
var content=
(
<Comment
author={item.author}
text={item.text}
key={item.id}/>
);
arr.push(content);
});
console.log(arr)
return (
<ul>{arr}</ul>
);
}
});
// 最高层对象App,包括两个中层组件
var App=React.createClass({
getInitialState:function(){
return {
data:[]
};
},
loadServer:function(){
var _this=this;
$.getJSON(this.props.url,function(data){
_this.setState({
data:data
})
});
},
componentDidMount:function(){
console.log(this.props.timer)
var _this=this;
setInterval(function(){
_this.loadServer();
},_this.props.timer)
},
render:function(){
//console.log(this.state)
return (
<div>
<h1>当前评论</h1>
<CommentList data={this.state.data}/>
<CommentForm/>
</div>
);
}
});
// 渲染模块
ReactDOM.render(
<App url="json.json" timer={2000}/>,
document.getElementById('example')
);
数据就流动起来了。如果你修改了服务器,定时器会在2s后重新更新所得到的数据。
四. markdown语法
这部分主要是调用remarkable插件,渲染你看到的数据。而渲染自然是在底层的Comment组件上完成。
所以我把Comment组件改成这样:
// 最底层的组件Comment,隶属于CommentList
var Comment=React.createClass({
render:function(){
var md=new Remarkable();//调用插件
var commentContent=md.render(this.props.text.toString());//渲染获得的字符串!
return (
<li>
<h2>{this.props.author}</h2>
<span>{commentContent}</span>
</li>
);
}
});
结果就搞笑了。纯文本在渲染引擎渲染之后变成了带P标签的内容。

解决方案:再此需要一个官方定义的props——
dangerouslySetInnerHTML
实现方法如下:
// 最底层的组件Comment,隶属于CommentList
var Comment=React.createClass({
getContent:function(){
var md=new Remarkable();//调用插件
var commentContent=md.render(this.props.text.toString());//渲染获得的字符串!
return ({
__html:commentContent
});//注意是两个下划线!
},
render:function(){
return (
<li>
<h2>{this.props.author}</h2>
<span dangerouslySetInnerHTML={this.getContent()}/>
</li>
);
}
});
五.添加新评论
到目前为止一切看起来还算简单。现在需要加新的评论。
CommentForm添加的是一个新的表单。里面包含了评论的大名,评论内容,还有提交按钮。
var CommentForm=React.createClass({
render:function(){
//console.log(this.props)
return (
<form>
<input type="text" placeholder="你的大名"/><br/>
<textarea type="text" placeholder="评论内容"></textarea><br/>
<button type="submit">提交</button>
</form>
);
}
});
在实现这个组件的时候,需要考虑它的状态。文本框的内容显然是状态。所以用一个state来保存它的状态。输入一次就保存一次并返回到文本框的value之中。
var CommentForm=React.createClass({
getInitialState:function(){
return ({
author:"",
text:""
});
},//初始化状态
authorChange:function(e){
this.setState({
author:e.target.value
});
},
textChange:function(e){
this.setState({
text:e.target.value
})
},
render:function(){
//console.log(this.props)
return (
<form>
<input
type="text"
placeholder="你的大名"
value={this.state.author}
onChange={this.authorChange}/><br/>
<textarea type="text"
placeholder="评论内容"
value={this.state.text}
onChange={this.textChange}></textarea><br/>
<button type="submit">提交</button>
</form>
);
}
});
组件已经变得很长很长,但是基本上也不需要想什么。
提交表单
提交表单做三件事,onSubmit在form标签上。
- 阻止跳转(e.preventDefault)
- 清空form的内容
- 返回到服务器并刷新列表
<form onSubmit={this.submit}>...
submit函数:
...
submit:function(e){
e.preventDefault();
// 接下来格式化获取内容!注意去掉评论头尾的空格。
var authorStr=this.state.author.trim();
var textStr=this.state.text.trim();
if(!textStr||!authorStr){
alert('你有地方忘了填!');
return false;
}//简单的表单校验
this.setState({
author:'',
text:''
});//清空表单内容
},
...
这就实现了前两步,但是提交到服务器并刷新好像用前端的方法无法实现。
我们之前做了每隔两秒钟刷新一次,所以每次都要拿数据,在这个案例中不现实。
所以为了不涉及太多无关知识,把定时器拿掉。
先不理它,还是做回调函数,把状态反馈到App:并刷新App的state:
返回的callback应该包括评论人名字,评论内容,说白了就是把这个对象扔进去作为参数。
那么id值呢?就用一个Data对象给他生成吧!(Date.now())
// 最底层的组件Comment,隶属于CommentList
var Comment=React.createClass({
getContent:function(){
var md=new Remarkable();//调用插件
var commentContent=md.render(this.props.text.toString());//渲染获得的字符串!
return ({
__html:commentContent
});//注意是两个下划线!
},
render:function(){
return (
<li>
<h2>{this.props.author}</h2>
<span dangerouslySetInnerHTML={this.getContent()}/>
</li>
);
}
});
//
// 中层对象,包括CommentList和CommentForm
var CommentForm=React.createClass({
getInitialState:function(){
return ({
author:"",
text:""
});
},//初始化状态
authorChange:function(e){
this.setState({
author:e.target.value,
});
},
textChange:function(e){
this.setState({
text:e.target.value,
})
},
submit:function(e){
e.preventDefault();
// 接下来格式化获取内容!注意去掉评论头尾的空格。
var authorStr=this.state.author.trim();
var textStr=this.state.text.trim();
if(!textStr||!authorStr){
alert('你有地方忘了填!');
return false;
}//简单的表单校验
this.props.callback({
"author":authorStr,
"text":textStr
});// 提交到服务器!
this.setState({
author:'',
text:''
});//清空表单内容
},
render:function(){
//console.log(this.props)
return (
<form onSubmit={this.submit}>
<input
type="text"
placeholder="你的大名"
value={this.state.author}
onChange={this.authorChange}/><br/>
<textarea type="text"
placeholder="评论内容"
value={this.state.text}
onChange={this.textChange}></textarea><br/>
<button type="submit">提交</button>
</form>
);
}
});
var CommentList=React.createClass({
render:function(){
var arr=[];
this.props.data.map(function(item){
var content=
(
<Comment
author={item.author}
text={item.text}
key={item.id}/>
);
arr.push(content);
});
return (
<ul>{arr}</ul>
);
}
});
// 最高层对象App,包括两个中层组件
var App=React.createClass({
getInitialState:function(){
return {
data:[]
};
},
loadServer:function(){
var _this=this;
$.getJSON(this.props.url,function(data){
_this.setState({
data:data
})
});
},
componentDidMount:function(){
this.loadServer();
// 服务器环境设置
// var _this=this;
// setInterval(function(){
// _this.loadServer();
// },_this.props.timer)
},
refreshComment:function(comment) {
console.log(comment)//假设已经提交了
comment.id=Date.now()//给他一个id值!
var newComments=this.state.data.concat([comment]);//把它桥接起来!
console.log(newComments)
// 接下来再获取一次。
// 服务器环境下可以这样做
// $.ajax({
// url: this.props.url,
// dataType: 'json',
// type: 'POST',
// data: comment,
// success: function(data) {
// //console.log(data)
// this.setState({data: data});
// }.bind(this),
// error: function(xhr, status, err) {
// console.error(this.props.url, status, err.toString());
// }.bind(this)
// });
//非服务器环境设置一个新状态就可以了。
this.setState({
data:newComments
})
},
render:function(){
//console.log(this.state)
return (
<div>
<h1>当前评论</h1>
<CommentList data={this.state.data}/>
<CommentForm callback={this.refreshComment}/>
</div>
);
}
});
// 渲染模块
ReactDOM.render(
<App url="json.json" timer={2000}/>,
document.getElementById('example')
);
效果支持简单的markdown语法:

React.js入门笔记(再续):评论框的实现的更多相关文章
- React.js入门笔记
# React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...
- React.js入门笔记(续):用React的方式来思考
本文主要内容来自React官方文档中的"Thinking React"部分,总结算是又一篇笔记.主要介绍使用React开发组件的官方思路.代码内容经笔者改写为较熟悉的ES5语法. ...
- React.js入门笔记 创建hello world 的6种方式
一.ReactJS简介 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站. ...
- React.js 入门与实战之开发适配PC端及移动端新闻头条平台课程上线了
原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,文章中是目前整个课程的大纲,以后此课程还会保持持续更新,此大纲文档也会保持更新, ...
- React.js入门小案例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...
- React.js 入门与实战课程思维导图
原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,在这里分享了课程中的思维导图,供大家参考. 原文发表于我的技术博客 此导图为课程 ...
- 前端框架React Js入门教程【精】
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- React.js - 入门
React.js - 第1天 1. React简介 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 ...
- React.js入门
React 入门实例教程 现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. ...
随机推荐
- 解决apache启动错误"httpd:Could not reliably determine..."
启动apache遇到错误:httpd: Could not reliably determine the server's fully qualified domain name [root@serv ...
- SQL Sever 博客文章目录(2016-07-06更新)
SQL Server方面的博客文章也陆陆续续的写了不少了,顺便也将这些知识点整理.归纳一下下.方便自己和他人查看. MS SQL 数据类型 三大数据库对比研究系列--数据类型 MS SQL 表和视图 ...
- mongodb 3.x 之实用新功能窥看[1] ——使用TTLIndex做Cache处理
mongodb一直都在不断的更新,不断的发展,那些非常好玩也非常实用的功能都逐步加入到了mongodb中,这不就有了本篇对ttlindex的介绍, 刚好我们的生产业务场景中就有这个一个案例... 一: ...
- MySql踩坑总结
衣带渐宽终不悔,为伊消得人憔悴,众里寻他千百度,蓦然回首,那人却在灯火阑珊处好通顺的句子哈哈 转了那么多弯,才明白问题就在一个地方.睡觉之前想明白了问题,还是经验太少.王国维的治学三境界: 昨夜西风凋 ...
- VS 母版使用配置技巧
采用web.config配置母版,方便母版的变更,处理方法: 1.在web.config配置如下内容: <configuration> <system.web> <pag ...
- 【Linux】重定向与管道
重定向 redirection 每个命令有输入源和输出目的地,默认行为,是标准输入和标准输出.大多数情况,标准输入是键盘,标准输出是屏幕.可以为单独的操作修改输入和输出,这就是重定向.重定向可以使某个 ...
- 5-4 bash脚本编程之三 条件判断及算术运算
1. 反引号是引用执行结果,并非是返回值 如下是错误的,结果是一行行记录,不是返回值 放大为: 练习 2. shell中如何进行算术运算 A=3 B=4 1. let算术运算表达式 2. $[算术运算 ...
- java动态编译笔记
1 前言 Java的动态编译知识,真真在实际开发中并不是经常遇到.但是学习java动态编译有助于我们从更深一层次去了解java.对掌握jdk的动态代理模式,这样我们在学习其他一些开源框架的时候就能够知 ...
- 【FLUENT案例】04:利用DDPM+DEM模拟鼓泡流化床
1 引言2 问题描述3 准备4 FLUENT前处理 1 引言 DEM碰撞模型扩展了DPM模型的功能,能够用于稠密颗粒流动的模拟.该模型可以与DDPM(Dense DPM)模型何用以模拟颗粒对主相的阻碍 ...
- (哈夫曼树)HuffmanTree的java实现
参考自:http://blog.csdn.net/jdhanhua/article/details/6621026 哈夫曼树 哈夫曼树(霍夫曼树)又称为最优树. 1.路径和路径长度在一棵树中,从一个结 ...