React.js入门笔记(再续):评论框的实现
2016-12-18 18:16
483 查看
本案例来自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入门笔记 创建hello world 的6种方式
- react.js入门笔记
- js学习入门教程笔记:css+html+js用户注册代码实现
- Arduino入门笔记(7):利用1602、1302实现时钟和定时器
- THREE.JS入门教程(6)创建自己的全景图实现步骤
- 牛腩新闻发布系统笔记8:新闻评论操作类的实现
- Node.js入门学习笔记-IDE选择/配置之WebStorm(windows)
- AT91SAM7S64入门笔记----精准延时的实现
- js实现简单的星级选择器提交效果适用于评论等
- BBS项目笔记之九:js实现动态的导航
- THREE.JS入门教程(6)创建自己的全景图实现步骤
- 游戏编程入门学习笔记26——AI篇——AI的实现
- 学习笔记---使用prototype.js扩展struts标签实现xmlhttprequest
- js实现无刷新评论
- QT入门笔记--信号和槽(附简单的C++类实现代码)
- 【笔记】通过 js——实现 各种跨域
- ITCAST视频-Spring学习笔记(使用Spring的注解方式实现AOP入门)
- 用JS实现移动的窗口 - 流星絮语 JAVA学习笔记 - CSDNBlog
- JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现
- 客户端网络pomelo学习笔记 (3) node.js 与 c 客户端 Diffie-Hellman 密钥交换算法的实现客户端网络