当前位置:   article > 正文

React组件之评论列表案例_react 移动端评论组件开发

react 移动端评论组件开发

根据前期所介绍的组件基础,实现一个评论列表的案例,要实现的功能分为四个部分:

  • 渲染评论列表(列表渲染)
  • 没有评论数据时渲染:暂无评论(条件渲染)
  • 获取评论信息,包括评论人和评论内容(受控组件)
  • 发表评论,更新评论列表(setState())

初始搭建的页面结构为:

<style>
        .app{
            margin:20px auto;
            border:1px solid #ccc;
            width:270px;
            height:100%;
            padding:10px;
        }
        .user{
            width:260px;
            height: 15px;
        }
        .content{
            width:260px;
            margin-top:10px;
        }
    </style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root')
        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='请输入评论内容'></textarea>
                    <br />
                    <button>发表评论</button>
                    </div>
                    <div className='no-comment'>暂无评论,快去评论吧!</div>
                    <ul>
                        <li>
                            <h3>评论人:王欢</h3>
                            <p>评论内容:前端!!!</p>
                        </li>
                    </ul>
                   </div>
               )
           }
        }
        //元素渲染
        ReactDOM.render(<App />,root)
    </script>
</body>
  • 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

实现效果为:
在这里插入图片描述
接下来,就来一一实现其功能。如下所示:

1. 渲染评论列表

① 在 state 中初始化评论列表数据
② 使用数组的map方法遍历state中的列表数据
③ 给每个被遍历的li元素添加key属性
如下所示:

 //初始化状态
state = {
    comments:[
        {id:1,name:'小欢',content:'好好学习!'},
        {id:1,name:'小熊',content:'天天向上!'},
        {id:1,name:'小冉',content:'大佬出场!'}
    ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
<ul>
{
  this.state.comments.map(item=>(
      <li key={item.id}>
          <h3>评论人:{item.name}</h3>
          <p>评论内容:{item.content}</p>
      </li>
   ))
 }
</ul>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现效果为:
在这里插入图片描述

2. 渲染暂无评论

① 判断列表数据的长度是否为0
② 如果为0,则渲染暂无评论
如下:

 {/* 渲染评论列表 */}
{ 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>)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

当将state里面的内容注释掉,可以得到:
在这里插入图片描述

3. 获取评论信息

① 使用受控组件方式处理表单元素
如下所示:
在state里面定义input和textarea输入的初始值,并获取输入的值,

 state = {
    comments:[
           //{id:1,name:'小欢',content:'好好学习!'},
          // {id:1,name:'小熊',content:'天天向上!'},
           //{id:1,name:'小冉',content:'大佬出场!'}
       ],
       username:'',
       userContent:''
   }
   handleForm=(e)=>{
       const {name,value}=e.target
       this.setState({
           [name]:value
       })
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
 <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}></textarea>
  • 1
  • 2
  • 3

实现效果为:
在这里插入图片描述

4. 发表评论

① 给按钮绑定单击事件
② 在事件处理程序中,通过state获取评论信息
③ 将评论信息添加到state中,并调用 setState() 方法更新state
如下所示:

 add=()=>{
	  const {comments,userName,userContent} = this.state
	  const newComments = [{id:Math.random(),name:userName,content:userContent},...comments]
	   this.setState({
	       comments:newComments
	   })
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  <button onClick={this.add}>发表评论</button>
  • 1

此时的实现效果为:
在这里插入图片描述
基本实现。但是我们发现这样并不美观,当我们内容发表完成后,文本框的内容并没有清空,而且不输入任何内容也可以发布。所以,我们接下来还要进行边界判断:
④ 边界情况:清空文本框
⑤ 边界情况:非空判断
如下所示:
如果输入内容为空,则弹出警示框,提示:请输入内容;且当输入内容发布完成后,文本框的内容清空。

//清除文本框的值即将state清空
this.setState({
	comments:newComments,
	  userName:'',
	  userContent:''
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
 add=()=>{
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:''
   })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

实现效果为:
在这里插入图片描述
完整代码为:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../react的js库/react.development.js"></script>
    <script src="../react的js库/react-dom.development.js"></script>
    <script src="../react的js库/babel.min.js"></script>
    <style>
        .app{
            margin:20px auto;
            border:1px solid #ccc;
            width:270px;
            height:100%;
            padding:10px;
        }
        .user{
            width:260px;
            height: 15px;
        }
        .content{
            width:260px;
            margin-top:10px;
        }
    </style>
</head>
<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root')
        class App extends React.Component{
            //初始化状态
            state = {
                comments:[
                    // {id:1,name:'小欢',content:'好好学习!'},
                    // {id:2,name:'小熊',content:'天天向上!'},
                    // {id:3,name:'小冉',content:'大佬出场!'}
                ],
                userName:'',
                userContent:''
            }
            handleForm=(e)=>{
                const {name,value}=e.target
                this.setState({
                    [name]:value
                })
            }
            add=()=>{
                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(){
               return (
                   <div className='app'>
                    <div >
                    <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}></textarea>
                    <br />
                    <button onClick={this.add}>发表评论</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>)}
                   </div>
               )
           }
        }
        //元素渲染
        ReactDOM.render(<App />,root)
    </script>
</body>
</html>
  • 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
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/549999
推荐阅读
相关标签
  

闽ICP备14008679号