React组件基础案例——评论列表
案例:需求分析
1. 渲染评论列表 (列表渲染)
2. 没有评论数据时渲染:暂无评论 (条件渲染)
3.获取评论信息,包括评论人和评论内容 (受控组件)
4. 发表评论,更新评论列表(setState())
案例:实现步骤
1. 渲染评论列表
1. 在state中初始化评论列表数据
2. 使用数组的map方法遍历state中的列表数据
3. 给每个被遍历的li元素添加key属性
//1. 导入react import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { // 初始化状态 state = { Comments: [ { id: 1, name: 'jack', content: '沙发!!!'}, { id: 2, name: 'rose', content: '板凳~'}, { id: 3, name: 'tom', content: '楼主好人'}, ] } 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> { this.state.Comments.map(item => ( <li key={item.id}> <h3>评论人:{item.name}</h3> <p>评论内容:{item.content}</p> </li> )) } </ul> </div> ) } } //渲染组件 ReactDOM.render(<App />, document.getElementById('root'))
2.渲染暂无评论
1. 判断列表数据的长度是否为0
2. 如果为0;则渲染暂无评论
//1. 导入react import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { // 初始化状态 state = { Comments: [ { id: 1, name: 'jack', content: '沙发!!!'}, { id: 2, name: 'rose', content: '板凳~'}, { id: 3, name: 'tom', content: '楼主好人'}, ] } // 渲染评论列表: 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> ) // return this.state.Comments.length === 0 ? ( // <div className="no-comment">暂无评论,快去评论吧~</div> // ) : ( // <ul> // {this.state.Comments.map(item => ( // <li key={item.id}> // <h3>评论人:{item.name}</h3> // <p>评论内容:{item.content}</p> // </li> // ))} // </ul> // ) } 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> {/* 通过条件渲染决定渲染什么内容: */} {/* {this.state.Comments.length === 0 ? ( <div className="no-comment">暂无评论,快去评论吧~</div> ) : ( <ul> {this.state.Comments.map(item => ( <li key={item.id}> <h3>评论人:{item.name}</h3> <p>评论内容:{item.content}</p> </li> ))} </ul> )} */} {this.renderList()} </div> ) } } //渲染组件 ReactDOM.render(<App />, document.getElementById('root'))
3. 获取评论信息
1. 使用受控组件方式处理表单元素
//1. 导入react import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { // 初始化状态 state = { Comments: [ { id: 1, name: 'jack', content: '沙发!!!'}, { id: 2, name: 'rose', content: '板凳~'}, { id: 3, name: 'tom', 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> ) // return this.state.Comments.length === 0 ? ( // <div className="no-comment">暂无评论,快去评论吧~</div> // ) : ( // <ul> // {this.state.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 }) } 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>发表评论</button> </div> {/* 通过条件渲染决定渲染什么内容: */} {/* {this.state.Comments.length === 0 ? ( <div className="no-comment">暂无评论,快去评论吧~</div> ) : ( <ul> {this.state.Comments.map(item => ( <li key={item.id}> <h3>评论人:{item.name}</h3> <p>评论内容:{item.content}</p> </li> ))} </ul> )} */} {this.renderList()} </div> ) } } //渲染组件 ReactDOM.render(<App />, document.getElementById('root'))
4. 发表评论
1. 给按钮绑定单击事件
2. 在事件处理程序中,通过state获取评论信息
3. 将评论信息添加到state中,并调用setState()方法更新state
//1. 导入react import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { // 初始化状态 state = { Comments: [ { id: 1, name: 'jack', content: '沙发!!!'}, { id: 2, name: 'rose', content: '板凳~'}, { id: 3, name: 'tom', 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> ) // return this.state.Comments.length === 0 ? ( // <div className="no-comment">暂无评论,快去评论吧~</div> // ) : ( // <ul> // {this.state.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 // console.log(userName,userContent) const newComments = [{ id: Math.random(), name: userName, content: userContent }, ...Comments] // console.log(newComments); this.setState({ Comments:newComments }) } 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.state.Comments.length === 0 ? ( <div className="no-comment">暂无评论,快去评论吧~</div> ) : ( <ul> {this.state.Comments.map(item => ( <li key={item.id}> <h3>评论人:{item.name}</h3> <p>评论内容:{item.content}</p> </li> ))} </ul> )} */} {this.renderList()} </div> ) } } //渲染组件 ReactDOM.render(<App />, document.getElementById('root'))
5.边界情况:清空文本框
6.边界情况:非空判读
//1. 导入react import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component { // 初始化状态 state = { Comments: [ { id: 1, name: 'jack', content: '沙发!!!'}, { id: 2, name: 'rose', content: '板凳~'}, { id: 3, name: 'tom', 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> ) // return this.state.Comments.length === 0 ? ( // <div className="no-comment">暂无评论,快去评论吧~</div> // ) : ( // <ul> // {this.state.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 } // console.log(userName,userContent) //将评论信息添加到state中 const newComments = [{ id: Math.random(), name: userName, content: userContent }, ...Comments] // console.log(newComments); //文本框的值如何清空? 要清空文本框只需要将其对应的state清空即可 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.state.Comments.length === 0 ? ( <div className="no-comment">暂无评论,快去评论吧~</div> ) : ( <ul> {this.state.Comments.map(item => ( <li key={item.id}> <h3>评论人:{item.name}</h3> <p>评论内容:{item.content}</p> </li> ))} </ul> )} */} {this.renderList()} </div> ) } } //渲染组件 ReactDOM.render(<App />, document.getElementById('root'))
最终版
index.js
//1. 导入react import React from 'react'; import ReactDOM from 'react-dom'; import './index.css' class App extends React.Component { // 初始化状态 state = { Comments: [ { id: 1, name: 'jack', content: '沙发!!!'}, { id: 2, name: 'rose', content: '板凳~'}, { id: 3, name: 'tom', 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 } //将评论信息添加到state中 const newComments = [{ id: Math.random(), name: userName, content: userContent }, ...Comments] //更新state,并清空文本框的内容 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'))
index.css
.app { border:1px solid black; width: 260px; } .user{ width: 240px; margin-left: 10px; margin-top: 10px; } .content{ width: 240px; margin-left: 10px; margin-top: 10px; } .app button { margin-left: 10px; }
浙公网安备 33010602011771号