近期要在生产环境上使用react,所以,自己学习了一下,写了一个简单的留言板小程序。完整的代码可以到这里下载:message-board
Use
前端使用React,然后还有Bootstrap和jQuery,React负责前端展现,jQuery主要是向服务器发送ajax请求。
后端使用Flask和MongoDB,为前端提供数据。这里主要关注前端,对于后端不做过多说明。
使用webpack,对js文件进行打包。
About React
React是facebook开发一个用于前段交互的Javascript库。
刚刚开始使用,有这么几个特点:
1. 组件化开发。React提倡无状态的组件,便于重用。
2. VirtualDOM。React的性能比较高,得益于虚拟DOM。它不会每次都去直接操作DOM,因为操作DOM的代价是很大的,所以,它在内存中维护了虚拟DOM,通过计算虚拟DOM和浏览器上的DOM的变更进行操作。
3. 专注于View。React不是MVC框架,它只是一个专注于View的库,所以,它也可以和很多其他框架或者库一起使用。
4. 提供完成的生命周期。
Message Board
这个留言板小应用,主要有这样几个功能:
1.添加留言,一个表单:用户名和内容
2.列表展示,显示所有留言
3.简单的分页
Code
使用React,就要对应用进行组件的切分,尽量保持组件的无状态。
App
从宏观上组织整个应用,切分三个大组件:
1. MessageForm,添加留言表单。
2. MessageList,留言列表
3. Pager,留言的分页控制
当然,组件还可以继续划分。
子组件的数据都会回调到MessageBoard中,在这里统一控制。
MessageBoard.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
var React = require( "react" );
var MessageList = require( "./MessageList" );
var MessageForm = require( "./MessageForm" );
var Pager = require( "./Pager" );
var MessageBoard = React.createClass({
getInitialState : function (){
return {
messages: [],
page:0,
pages:0
}
},
submitMessage : function (author, content) {
$.ajax({
type: 'post' ,
url: '/message' ,
data:{author:author,content:content}
}).done( function (data) {
console.log(data);
this .listMessage(1);
}.bind( this ));
},
listMessage : function (page){
console.log( "listMessages page:" +page)
$.ajax({
type: 'get' ,
url: '/messages' ,
data:{page:page}
}).done( function (resp) {
if (resp.status == "success" ){
var pager = resp.pager;
console.log(pager);
this .setState({
messages:pager.messages,
page:pager.page,
pages:pager.pages
});
}
}.bind( this ));
},
componentDidMount : function (){
this .listMessage(1);
},
render : function (){
var pager_props = {
page : this .state.page,
pages : this .state.pages,
listMessage : this .listMessage
};
return (
<div>
<MessageForm submitMessage={ this .submitMessage}/>
<MessageList messages = { this .state.messages}/>
<Pager {...pager_props}/>
</div>
)
}
});
module.exports = MessageBoard;
|
MessageForm
一个简单的表单,保存留言。用户提交后,数据会传给父组件。
MessageForm.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
var React = require( "react" );
var MessageForm = React.createClass({
handleSubmit : function (e) {
e.preventDefault();
var author = this .refs.author.getDOMNode().value.trim();
var content = this .refs.content.getDOMNode().value.trim();
this .props.submitMessage(author,content);
this .refs.author.getDOMNode().value = "" ;
this .refs.content.getDOMNode().value = ""
},
render : function (){
return (
<div className= "well" >
<h4>Leave a Message:</h4>
<div role= "form" >
<div className= "form-group" >
<input ref= "author" className= "form-control" placeholder= "Name" />
<textarea ref= "content" className= "form-control" rows= "3" placeholder= "Leave your message here" ></textarea>
</div>
<a className= "btn btn-primary" onClick={ this .handleSubmit}>Submit</a>
</div>
</div>
)
}
});
module.exports = MessageForm;<br>
|
MessageList
留言的列表展示,在写列表之前,把每条留言写成一个组件
Message.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
var React = require( "react" );
var Message = React.createClass({
render : function (){
var msg = this .props.message;
return (
<div>
<h3>{msg.author}
<small>{msg.time.toLocaleString()}</small>
</h3>
<p>{msg.content}</p>
</div>
)
}
});
module.exports = Message;
|
然后,再写列表.
数据从父组件通过props传递进来
MessageList.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var React = require( "react" );
var Message = require( "./Message" );
var MessageList = React.createClass({
render : function () {
var messages = this .props.messages.map( function (item){
return <Message message={item}/>
});
console.log(messages);
return (
<div>
{messages}
</div>
)
}
});
module.exports = MessageList;
|
Pager
这是一个简单的分页,会显示当前页和总页数,还有上一页和下一页功能。
Pager.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
var React = require( "react/addons" );
var Pager = React.createClass({
getDefaultProps : function (){
return {
page:0,
pages:0
}
},
clickHandler: function (e){
e.preventDefault();
console.log(e.target.dataset.page);
console.log(e.target.dataset.page.value);
this .props.listMessage(e.target.dataset.page);
},
render : function (){
var cx = React.addons.classSet;
var preClass = cx({
'previous' : true ,
'disabled' : this .props.page == 1
});
var nextClass = cx({
'next' : true ,
'disabled' : this .props.page == this .props.pages
});
return (
<ul className= "pager" >
<li className={preClass} onClick={ this .clickHandler}>
<a href= "#" data-page={ this .props.page-1}>←Prev</a>
</li>
<li>
<span>{ this .props.page}/{ this .props.pages}</span>
</li>
<li className={nextClass} onClick={ this .clickHandler}>
<a href= "#" data-page={ this .props.page+1}>Next→</a>
</li>
</ul>
)
}
});
module.exports = Pager;
|
Summary
一个简单的小程序只能简单的感受一下React,这个库的思路和当前流行的库和框架相比,还是比较新颖的,值得学习~