需求分析
- 渲染评论列表(列表渲染)
- 没有评论数据时渲染:暂无评论(条件渲染)
- 获取评论信息,包括评论人和评论内容(受控组件)
- 发表评论,更新评论列表(
setState()
)
搭建评论列表的模板
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
class App extends React.Component {
render() {
return (
<div className="app">
<div>
<input className="user" type="text" placeholder="请输入评论人" />
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
/>
<br />
<button>发表评论</button>
</div>
<div className="no-comment">暂无评论,快去评论吧~</div>
<ul>
<li>
<h3>评论人:多多</h3>
<p>评论内容:加油!!!</p>
</li>
</ul>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'))
.app {
width: 300px;
padding: 10px;
border: 1px solid #999;
}
.user {
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}
.content {
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}
.no-comment {
text-align: center;
margin-top: 30px;
}
渲染评论列表
- 在state中初始化评论列表数据
state = {
comments: [
{ id: 1, name: '图图', content: '真不错!!!' },
{ id: 2, name: '一多', content: '+1' },
{ id: 3, name: '一凡', content: '加油加油!' }
]
}
- 使用数组的
map
方法遍历 state
中的列表数据 - 给每一个被遍历的 li 元素添加
key
属性 - 在
render
方法里的 ul 节点下嵌入表达式
{
this.state.comments.map(item => {
return (
<li key={item.id}>
<h3>{item.name}</h3>
<p>{item.content}</p>
</li>
)
})
}
渲染暂无评论
- 判断列表数据的长度是否为0
- 如果为0,则渲染暂无评论
- 如果不为0,那么渲染列表数据
- 在jsx中大量写逻辑会导致很臃肿,所以我们可以把条件渲染的逻辑抽取成一个函数
renderList(){
if (this.state.comments.length === 0) {
return (<div className="no-comment">暂无评论,快去评论吧~</div>)
} else {
return (
<ul> {
this.state.comments.map(item => {
return (
<li key={item.id}>
<h3>{item.name}</h3>
<p>{item.content}</p>
</li>
)
})
}
</ul>
)
}
}
- 在
render
的 return方法
里面调用这个函数即可
render() {
return (
<div>
...
{}
{this.renderList()}
</div>
)
}
获取评论信息
- 通过受控组件来获取内容
- 初始化用户名和用户内容的state
userName: '',
userContent: ''
- 在结构中,把表单元素的
value
与 state
进行绑定,还需要绑定 name
属性和 onChange
属性
<input className="user" type="text" placeholder="请输入评论人" value={this.state.userName} name="userName" onChange={this.handleForm}/>
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
value={this.state.userContent}
name="userContent"
onChange={this.handleForm}
/>
- 在
handleFrom
函数中利用setState
来让数据保持一致
handleForm = (e) => {
this.setState({
[e.target.name] : e.target.value
})
}
发表评论
- 给按钮绑定事件
- 在事件处理程序中,通过state获取评论信息
- 将评论信息添加到state中,利用setState来更新页面
- 添加评论前需要判断用户是否输入内容
- 添加评论后,需要情况文本框用户输入的值
handleClick = (e) => {
let {userName,userContent} = this.state
if(userName.trim()==='' || userContent.trim() === ''){
alert('请输入内容')
return
}
let newComments = [{
id: this.state.comments.length+1,
name: userName,
content: userContent
},...this.state.comments]
this.setState({
comments: newComments,
userName:'',
userContent: ''
})
}
综合代码
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
class App extends React.Component {
state = {
comments: [
{ id: 1, name: '图图', content: '真不错!!!' },
{ id: 2, name: '一多', content: '+1' },
{ id: 3, name: '一凡', content: '加油加油!' }
],
userName: '',
userContent: ''
}
renderList() {
const { comments } = this.state
if (comments.length === 0) {
return <div className="no-comment">暂无评论,快去评论吧~</div>
}
return (
<ul>
{comments.map(item => (
<li key={item.id}>
<h3>评论人:{item.name}</h3>
<p>评论内容:{item.content}</p>
</li>
))}
</ul>
)
}
handleForm = e => {
const { name, value } = e.target
this.setState({
[name]: value
})
}
addComment = () => {
const { comments, userName, userContent } = this.state
if (userName.trim() === '' || userContent.trim() === '') {
alert('请输入评论人和评论内容')
return
}
const newComments = [
{
id: Math.random(),
name: userName,
content: userContent
},
...comments
]
this.setState({
comments: newComments,
userName: '',
userContent: ''
})
}
render() {
const { userName, userContent } = this.state
return (
<div className="app">
<div>
<input
className="user"
type="text"
placeholder="请输入评论人"
value={userName}
name="userName"
onChange={this.handleForm}
/>
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
value={userContent}
name="userContent"
onChange={this.handleForm}
/>
<br />
<button onClick={this.addComment}>发表评论</button>
</div>
{}
{this.renderList()}
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'))