React组件实践
最近在学习React,上一篇写了自己React入门的一些笔记。组件component作为React的主要特性,于是作为自己的实践开发了评论组件,一般上是需要与后台交互,但为了简便就省了这一步,而直接在页面造了假数据进行测试。
组件结构
|– CommentBox
|– CommentList
|– Comment
|– Pagination
|– CommentForm
Comment子组件
该组件相对简单,作为每条评论的UI显示,包括用户名和评论。所以只需使用render()方法即可。
1 | var Comment = React.createClass({ render: function() { return ( <div className="list-group-item"> <div className="row-action-primary"> <i className="mdi-file-folder"></i> </div> <div className="row-content"> <h4 className="list-group-item-heading">{this.props.username}</h4> <p className="list-group-item-text">{this.props.comment}</p> </div> </div> ); } }); |
用户名和评论分别使用组件的参数this.props.username和this.props.comment传递。
Pagination子组件
该组件用于评论列表的分页,以curPage当前页作为组件的状态state,每次该值的更新,更新组件的UI显示,并调用父组件CommentList的changePage()方法更新评论列表。
1 | var Pagination = React.createClass({ getInitialState: function() { return { curPage: 1 } }, handlePageChange: function(num,e) { e.preventDefault(); var curPage = this.state.curPage; var total = this.props.total; if(num=='pre') { num = curPage == 1? curPage: curPage - 1; } else if(num == 'next') { num = curPage == total? curPage: curPage + 1; } this.setState({curPage:num}); this.props.changePage(num); }, render: function() { var total = this.props.total; var page = Array.apply(null,{length:total}).map(function(i,index){return index+1}); var curPage = this.state.curPage; var _this =this; return( <ul className="pagination pagination-sm"> <li className={curPage==1?"disabled":""}><a href="#" onClick={_this.handlePageChange.bind(null,'pre')}>«</a></li> { page.map(function(i) { //这是的this指向窗口 return ( <li className={curPage==i?"active":""}> <a href="#" onClick={_this.handlePageChange.bind(null,i)}>{i}</a> </li> ) }) } <li><a href="#" onClick={_this.handlePageChange.bind(null,'next')}>»<div className={curPage==total?"disabled":"ripple-wrapper"}></div></a></li> </ul> ) } }); |
在render()方法中根据页数(total组件参数)显示页码。当前页码使用className={curPage==i?"active":""}自动更新样式。
有点要注意,在map()方法回调函数中this指向的是window当前窗口。而a链接标签click事件onClick={_this.handlePageChange.bind(null,i)}使用bind方法可向事件处理函数传递参数。
事件处理中需调用this.setState()更新组件的状态,随后调用父组件的方法更新评论列表。
CommentList组件
评论列表组件,以curPage当前页作为组件的状态state。
1 | var CommentList = React.createClass({ getInitialState: function(){ return { curPage: 1 }; }, getDefaultProps: function() { return { count: 5 }; }, handlePageChange: function(num) { this.setState({curPage: num}) }, render: function() { var curPage = this.state.curPage; var count = this.props.count; var list = this.props.list.slice((curPage - 1) * count, count * curPage); var total = Math.ceil(this.props.list.length / count) return ( <div className="list-group"> { list.map(function(item){ return ( <div> <Comment username={item.name} comment={item.comment} /> <div className="list-group-separator"></div> </div> ); }) } <Pagination total={total} changePage={this.handlePageChange} /> </div> ) } }); |
CommentForm组件
评论表单组件,提交表单调用父组件方法this.props.onHandleSubmit()更新评论列表。
1 | var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var usernameInput = React.findDOMNode(this.refs.usernameInput); var commentInput = React.findDOMNode(this.refs.commentInput); var data = { name: usernameInput.value, comment: commentInput.value } if(data.name.trim() == '' || data.comment.trim()=='') return; this.props.onHandleSubmit(data); usernameInput.value=''; commentInput.value='' return ; }, render: function() { return ( <form className="form-horizontal" onSubmit={this.handleSubmit}> <fieldset> <legend>我要评论</legend> <div className="form-group"> <div className="form-control-wrapper"> <input className="form-control empty" ref="usernameInput" id="focusedInput" type="text" /> <div className="floating-label">用户名</div> </div> </div> <div className="form-group"> <div className="form-control-wrapper"> <textarea className="form-control empty" ref="commentInput" rows="3" id="textArea"></textarea> <div className="floating-label">评论</div> </div> </div> <div className="form-group"> <div className="col-lg-10 col-lg-offset-2"> <button className="btn btn-default">Cancel</button> <button type="submit" className="btn btn-primary">Submit</button> </div> </div> </fieldset> </form> ) } }); |
CommentBox组件
以评论列表数据list作为组件的状态,更新时将CommentForm提交的评论添加到list的头部。
1 | var CommentBox = React.createClass({ getInitialState: function() { return {list:this.props.list}; }, updateList: function(data) { var list = this.state.list; list.unshift(data); this.setState({list:list}) }, render: function() { return ( <div> <CommentList list={this.state.list} {...this.props}/> <CommentForm onHandleSubmit={this.updateList}/> </div> ) } }) |
使用CommentBox组件
1 | // 测试数据 var commentList = [ {name:'user1',comment: 'hello world1'}, {name:'user2',comment: 'hello world2'}, {name:'user3',comment: 'hello world3'}, {name:'user4',comment: 'hello world4'}, {name:'user5',comment: 'hello world1'}, {name:'user6',comment: 'hello world2'}, {name:'user7',comment: 'hello world3'}, {name:'user8',comment: 'hello world4'}, {name:'user9',comment: 'hello world1'}, {name:'user10',comment: 'hello world2'}, {name:'user11',comment: 'hello world3'}, {name:'user12',comment: 'hello world4'}, {name:'user13',comment: 'hello world3'}, {name:'user14',comment: 'hello world4'}, ]; React.render( <CommentBox list={commentList} count={10}/>, document.getElementById('commentBox') ) |