http://blog.csdn.net/zhouziyu2011/article/details/70504651实现了不考虑服务器,直接将 JSON 数据写在代码中的模拟从服务器获取数据。
本文继续进行两方面的改进:
1、给组件引进可变的 state
2、从JSON文件从获取数据
1、给组件引进可变的 state
之前的代码中每个组件都是基于自己的props渲染自己,但props 是不可变的,它们从父级传来并被父级拥有。
为实现交互,给组件引进了可变的 state,this.state是组件私有的,可通过调用 this.setState() 改变它,每当state更新,组件就重新渲染自己。
var CommentBox = React.createClass({
getInitialState: function() {
return {
data: [
{id: 1, author: "Alice", text: "This is Alice's comment"},
{id: 2, author: "Bruce", text: "This is Bruce's comment"}
]
};
},
render: function() {
return (
<div className="commentBox">
<h1>CommentBox</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function(comment) {
return <Comment author={comment.author} key={comment.id}>{comment.text}</Comment>
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h3>{this.props.author}</h3>
{this.props.children}
</div>
);
}
});
var CommentForm = React.createClass({
render: function() {
return (
<div className="commentForm">
CommentForm
</div>
);
}
});
ReactDOM.render(
<CommentBox />,
document.getElementById('commentBox')
);
2、从JSON文件从获取数据
当组件第一次创建时,从服务器获取JSON并更新状态以反映最新的数据,用jQuery的ajax()方法来发送一个异步请求到服务器以获取需要的数据,这些数据暂时从commentBox.json中获取:
commentBox.json文件:
[
{"id": 1, "author": "Cindy", "text": "This is Cindy's comment"},
{"id": 2, "author": "David", "text": "This is David's comment"}
]
注意:JSON格式的文件的键值对的属性和值都要用双引号括起来。
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render: function() {
return (
<div className="commentBox">
<h1>CommentBox</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function(comment) {
return <Comment author={comment.author} key={comment.id}>{comment.text}</Comment>
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h3>{this.props.author}</h3>
{this.props.children}
</div>
);
}
});
var CommentForm = React.createClass({
render: function() {
return (
<div className="commentForm">
CommentForm
</div>
);
}
});
ReactDOM.render(
<CommentBox url="commentBox.json"/>,
document.getElementById('commentBox')
);
componentDidMount() 是被React自动调用的方法,类似于JavaScript中的window.onload,在render()方法之后,也即组件渲染完毕之后,被React自动调用。
getComments()方法封装从服务器获取数据的Ajax调用。componentDidMount()每隔一定时间调用getComments()方法,实现对服务器的轮询。
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
getComments: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function() {
this.getComments();
setInterval(this.getComments, this.props.inteval);
},
submitComments: function(comment) {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render: function() {
return (
<div className="commentBox">
<h1>CommentBox</h1>
<CommentForm onCommentSubmit={this.submitComments}/>
<CommentList data={this.state.data} />
</div>
);
}
});
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function(comment) {
return <Comment author={comment.author} key={comment.id}>{comment.text}</Comment>
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
{this.props.author}:{this.props.children}
</div>
);
}
});
var CommentForm = React.createClass({
getInitialState: function() {
return {author: "", text: ""};
},
setAuthor: function(e) {
this.setState({author: e.target.value});
},
setText: function(e) {
this.setState({text: e.target.value});
},
submitComments: function(e) {
e.preventDefault();
var author = this.state.author.trim();
var text = this.state.text.trim();
if (text == "" || author == "")
return;
this.props.onCommentSubmit({author: author, text: text});
this.setState({author: "", text: ""});
},
render: function() {
return (
<form className="commentForm" onSubmit={this.submitComments}>
<input type="text" placeholder="Please enter your name!" value={this.state.author} onChange={this.setAuthor} /><br/><br/>
<input type="text" placeholder="Please enter your comment!" value={this.state.text} onChange={this.setText} /><br/><br/>
<input type="submit" value="submit" />
</form>
);
}
});
ReactDOM.render(
<CommentBox url="commentBox.json" inteval="5000"/>,
document.getElementById('commentBox')
);
CommentForm 组件渲染一个可以输入作者、评论并提交的表单,state带有 author 和 text 两个属性并初始化为空字符串,给表单的author 文本框字段和text文本框字段绑定一个onChange处理器,在字段更新后更新state的值,并给表单绑定一个onSubmit处理器,在表单提交输入后清空表单字段,并通过调用preventDefault()来阻止提交表单的默认行为。
当用户提交评论时,需要刷新评论列表来包含这条新评论,因此需要从子组件传回数据到它的父组件,在父组件的render()方法中传递一个新的回调函数submitComments到子组件,绑定它到子组件的 onCommentSubmit 事件上。
submitComments通过Ajax请求向服务器POST数据来刷新列表。需要注意的是,由于本实例中是用的是静态的JSON文件模拟服务器数据,因此发GET请求可以成功但POST请求则报错404 Not Found,这个问题在正常的服务器请求中不会出现。