评论列表(React组件基础案例)

    • 目标

目的:自己做记录,记录制作过程以及遇到的问题。内容来自b站的up主:黑马程序员(up主名字)的黑马程序员黑马程序员前端React视频教程....(视频名称部分)。

效果展示:

2. 开始制作

2.1 创建项目

新建一个文件夹,用vscode打开,在vscode中打开终端,在终端内数输入“npx create-react-app comm”(comm是项目名,自己取的)

创建好之后的样子

在终端输入“cd comm”,再输入“yarn start(/npm start)”

创建完成

完成基础样式,点开src文件夹里面的index.js,将里面的内容替换成如下

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';

// 评论列表案例
// comments: [
//   { id:1, name:'jack', content:'沙发!!!' },
//   { id:2, name:'andy ', content:'板凳!!!' },
//   { id:3, name:'tom', content:'楼主好人!!!' }
// ]

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>评论人:jack</h3>
            <p>评论内容:沙发!!!</p>
          </li>
        </ul>
      </div>
    )
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

打开src文件夹里的index.css,将里面的内容替换成如下:

.app {
  width: 233px;
  margin: 20px;
  padding-left: 10px;
  padding-top: 5px;
  border: 1px solid black;
}

.user {
  margin-bottom: 10px;
}

.content {
  margin-bottom: 10px;
}

.no-comment {
  margin-bottom: 10px;
}

更改完之后保存,打开浏览器,就是现在这样了

样式写的不好,小伙伴们可以改改

2.2 渲染评论列表

要渲染,首先就要有状态,所以我们先进行状态的初始化,在state中初始化评论列表数据

初始化状态后,就需要渲染数据,此时状态放在一个数组中,所以我们用map方法遍历数组,然后为每一个评论数据生成一个li元素,所以我们接下来处理下面的li元素。先将ul里面原有的li元素内容删掉。我们通过this.state.comments拿到评论列表数据,然后调用map方法进行遍历,给每个被遍历的li元素添加key属性

完成后的效果展示

2.3 渲染暂无评论

如果没有数据,就要渲染暂无数据,通过判断列表数据的长度是否为0,如果为0,则是暂无评论。

我们通过条件渲染,选择渲染什么内容。首先封装一个方法,通过renderList这个方法的返回值作为渲染的内容。

然后创建这个方法,通过三元表表达式的方式进行选择,将相应内容剪切(注意是剪切,所以先前在方面下面的那两个有无评论的内容就不在了)

效果展示

可以注释掉评论内容,看能否正常展示“无评论”时的效果

2.4 获取评论信息

使用受控组件方式处理表单元素。在我们的结构中一共有两个表单元素,一个“评论人”,一个“评论内容”,这两个都可以通过value的方式来获取,所以我们可以创建同一个事件处理程序来进行统一的获取。首先我们要准备一个状态

接下来把这两个状态设置为当前两个表单元素的值,然后添加name属性

然后添加事件处理程序,处理表单元素值。因为要拿到事件对象,因此先放个事件对象e,然后接下来对他们进行处理。首先拿到当前是哪一个表单,即name;然后接下来再通过setState更新状态,更新状态需要值,因此就需要value。

然后在表单元素中分别来一个change事件

点开浏览器,按F12进入调试界面,在文本框输入内容,可以看到react里的state在随之变化了,说明这两个表单元素现在都能受到受控组件的控制了。

2.5 发表评论

首先我们要给按钮绑定点击事件,然后来一个“发表评论”的事件处理程序

如何讲我们的数据添加到state中呢?此处我们选择将数据放在第一条评论之前。由于数据是添加给comments,所以我们应该先拿到comments的数据。拿到之后,通过数组的扩展运算符先拿到一个新的数据,然后再添加数据,因为我们是添加在前面,所以在“...comments”的前面添加一个对象(加对象是因为数组中的每一项都是一个对象,我们要保证加进来的数据结构与上面保持一致)

效果展示

2.5.1 边界情况

此时还存在两个问题:点击“发表评论”之后文本框不会自动清空;当什么都不输入或输入空格仍能发表。针对空格可以使用非空校验。如何清空文本框的值呢?文本框的值就是状态的值,要清空文本框就是清空状态,将它们置成空字符串即可

然后就完成啦。以下为index.js完整代码:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';

class App extends React.Component {
  state = {
    comments: [
        { id:1, name:'jack', content:'沙发!!!' },
        { id:2, name:'andy ', content:'板凳!!!' },
        { id:3, name:'tom', content:'楼主好人!!!' }
      ],
    // 评论人
    userName:'',
    // 评论内容
    userContent:''
  }

// 渲染评论列表
renderList() {
  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) => {
  this.setState({
    [e.target.name]:e.target.value
  })
}

addComment = () => {
  if (this.state.userName.trim() === '' || this.state.userContent.trim() === '') {
    alert('请输入评论人和评论内容')
    return
  }
  const newComments = [{
    id:Math.random(),
    name:this.state.userName,
    content:this.state.userContent
  },...this.state.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} />
          <br />
          <button onClick={this.addComment}>发表评论</button>
        </div>

        {this.renderList()}
      </div>
    )
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

猜你喜欢

转载自blog.csdn.net/qq_53767416/article/details/128587754