首页 > 网站 > WEB开发 > 正文

React实践(一)

2024-04-27 14:07:56
字体:
来源:转载
供稿:网友

React实践(一)

该实践取自官方教程:https://github.com/reactjs/react-tutorial

主要是自实现的过程以及一些心得体会

该实践是实现一个评论框。

  • 一个展示所有评论的视图
  • 一个提交评论的表单
  • 与后台的接口hook

特点:

  • 评论提交之前就先显示在列表中,提高体验
  • 其他用户的评论实时更新
  • 可用markdown格式编写文本

开始

下面就是我们的index.html模板文件,看官copy过去吧。之后的所有代码都写在script里面

 1 <!-- index.html --> 2 <html> 3   <head> 4     <title>Hello React</title> 5     <script src="http://fb.me/react-0.13.0.js"></script> 6     <script src="http://fb.me/JSXTransformer-0.13.0.js"></script> 7     <script src="http://code.jquery.com/jquery-1.10.0.min.js"></script> 8   </head> 9   <body>10     <div id="content"></div>11     <script type="text/jsx">12       // Your code here13     </script>14   </body>15 </html>

其中jquery不是对React必要的,只是我们想简化Ajax的代码

组件结构

React是全组件化的,可组装的。我们的组件结构如下:

- CommentBox  - CommentList    - Comment  - CommentForm

CommentBox

让我们先来把最基本的组件构造出来

 1 var CommentBox = React.createClass({ 2   render: function() { 3     return ( 4       <div className="commentBox"> 5         Hello, world! I am a CommentBox. 6       </div> 7     ); 8   } 9 });10 React.render(11   <CommentBox />,12   document.getElementById('content')13 );

从代码不难看出,也不过是简单的div罢了

CommentList、CommentForm

 1 var CommentList = React.createClass({ 2   render: function() { 3     return ( 4       <div className="commentList"> 5         Hello, world! I am a CommentList. 6       </div> 7     ); 8   } 9 });10 11 var CommentForm = React.createClass({12   render: function() {13     return (14       <div className="commentForm">15         Hello, world! I am a CommentForm.16       </div>17     );18   }19 });

这两个组件也不过就是div而已

那我们根据组件结构,把这两个组件放进CommentBox:

 1 var CommentBox = React.createClass({ 2   render: function() { 3     return ( 4       <div className="commentBox"> 5         <h1>Comments</h1> 6         <CommentList /> 7         <CommentForm /> 8       </div> 9     );10   }11 });

Comment

组件结构里,现在还剩CommentList里的Comment。我们想在评论中传评论人和评论文本过去。那我们来实现一下:

 1 var CommentList = React.createClass({ 2   render: function() { 3     return ( 4       <div className="commentList"> 5         <Comment author="Pete Hunt">This is one comment</Comment> 6         <Comment author="Jordan Walke">This is *another* comment</Comment> 7       </div> 8     ); 9   }10 });

我们已经从父组件CommenList传递了一些数据给子组件Comment

那我们来实现Comment组件,看官应该还记得,我们通过this.PRops在子组件中获取数据:

 1 var Comment = React.createClass({ 2   render: function() { 3     return ( 4       <div className="comment"> 5         <h2 className="commentAuthor"> 6           {this.props.author} 7         </h2> 8         {this.props.children} 9       </div>10     );11   }12 });

其中,this.props.children是任何内嵌的元素。

而前面说了,我们提供markdown格式的输入,那就修改一下。

添加Markdown

这里我们要用到第三方库Showdown,作用是处理Markdown文本且转换成原始HTML。

我们先添加<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>到head中

接着我们修改this.props.children,且添加Showdown的调用

 1 var converter = new Showdown.converter(); 2 var Comment = React.createClass({ 3   render: function() { 4     return ( 5       <div className="comment"> 6         <h2 className="commentAuthor"> 7           {this.props.author} 8         </h2> 9         {converter.makeHtml(this.props.children.toString())}10       </div>11     );12   }13 });

其中,为了转换成Showdown能处理的原始字符串,所以显示调用了toString()

但是React为了防止XSS,我们的显示会类似这样,<p>This is<em>another</em>comment</p>

并没有渲染成真正的HTML

当然我们这里有一个方法:

 1 var converter = new Showdown.converter(); 2 var Comment = React.createClass({ 3   render: function() { 4     var rawMarkup = converter.makeHtml(this.props.children.toString()); 5     return ( 6       <div className="comment"> 7         <h2 className="commentAuthor"> 8           {this.props.author} 9         </h2>10         <span dangerouslySetInnerHTML={{__html: rawMarkup}} />11       </div>12     );13   }14 });

注意:框架会警告你别使用这种方法

接入数据模型

上面,我们是把数据直接写入React中,实际开发中,数据是来自于数据库的,那我们这里就暂且用hard code的形式写在JSON对象中。

1 var data = [2   {author: "Pete Hunt", text: "This is one comment"},3   {author: "Jordan Walke", text: "This is *another* comment"}4 ];

我们需要把数据通过props的形式传到CommentList。而首先就是把数据传入到CommentBox

这里是React的单向数据流。关于这个,会在之后另开一篇文章来研究下。

 1 var CommentBox = React.createClass({ 2   render: function() { 3     return ( 4       <div className="commentBox"> 5         <h1>Comments</h1> 6         <CommentList data={this.props.data} /> 7         <CommentForm /> 8       </div> 9     );10   }11 });12 13 React.render(14   <CommentBox data={data} />,15   document.getElementById('content')16 );

这时候,CommentList就可以使用数据了。让我们来动态地去渲染评论,而不是之前一条一条地写<Comment >xxx</Comment>

来看下代码:

 1 var CommentList = React.createClass({ 2   render: function() { 3     var commentNodes = this.props.data.map(function (comment) { 4       return ( 5         <Comment author={comment.author}> 6           {comment.text} 7         </Comment> 8       ); 9     });10     return (11       <div className="commentList">12         {commentNodes}13       </div>14     );15   }16 });

就这样了。

从数据库获取数据

实际开发中,往往是后台提供了数据接口,而这时候,我们就需要这个接口跟我们上面的实现结合起来了。

而且,现在的这个组件在请求数据回来之前,是没有数据的。并且,评论是需要更新的。

我们之前是通过data传给CommentBox,每个组件也只在初始化的时候更新一次。

props是不可变的,它们从父节点传过来,被父节点所拥有。而为了实现交互,这里就需要用到state,this.state是组件私有的,当state变化的时候,组件会重新渲染自己。

关于props和state,之后也会写一篇来具体介绍一下。

1 React.render(2   <CommentBox url="comments.json" />,3   document.getElementById('content')4 );

因为,我们这里没有去实现后台,所以姑且用本地的文件comments.json来返回这个JSON对象,就创建一个comments.json文件放在index.html同目录下,把下面的复制进去:

// comments.json[  {"author": "Pete Hunt", "text": "This is one comment"},  {"author": "Jordan Walke", "text": "This is *another* comment"}]

这里我们用的是JQ的AJAX,下面是修改后的CommentBox:

 1 var CommentBox = React.createClass({ 2   getInitialState: function() { 3     return {data: []}; 4   }, 5   componentDidMount: function() { 6     $.ajax({ 7       url: this.props.url, 8       dataType: 'json', 9       success: function(data) {10         this.setState({data: data});11       }.bind(this),12       error: function(xhr, status, err) {13         console.error(this.props.url, status, err.toString());14       }.bind(this)15     });16   },17   render: function() {18     return (19       <div className="commentBox">20         <h1>Comments</h1>21         <CommentList data={this.state.data} />22         <CommentForm />23       </div>24     );25   }26 });

这里我们给CommentBox添加了一个data数组的state,作为取到的评论的保存。

组件会在组件构建完后,去取数据,动态更新的要点就是this.setState()

而我们的评论是实时更新的,即别人如果在数据库里添加了评论,那我们是要实时去检测是否更新了的。

这里我们就简单的用轮训的方法:

 1 var CommentBox = React.createClass({ 2   loadCommentsFromServer: function() { 3     $.ajax({ 4       url: this.props.url, 5       dataType: 'json', 6       success: function(data) { 7         this.setState({data: data}); 8       }.bind(this), 9       error: function(xhr, status, err) {10         console.error(this.props.url, status, err.toString());11       }.bind(this)12     });13   },14   getInitialState: function() {15     return {data: []};16   },17   componentDidMount: function() {18     this.loadCommentsFromServer();19     setInterval(
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表