react实现评论列表案例

在学习了 react 的 JSX 语法以及 类组件 后,现在我们来实现一个 评论列表案例

对应该案例主要有以下几个功能点:

  1. 列表展示功能
  2. 发表评论功能 
  3. 清空评论功能
  4. 删除评论功能

对于该案例的静态结构以及样式这里就不去过多的进行说明了,我们直接给出它的静态结构和样式

src/index.css

.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;
}

src/index.js

/**
 * 1. 导入react和react-dom
 * 2. 创建 react 元素
 * 3. 把 react 元素渲染到页面
 */
 import React from 'react';
 import ReactDom from 'react-dom/client';
 import { Component } from 'react';
 import './index.css'

/* 
  主要实现的功能:
    1. 展示评论功能
    2. 清空评论功能
    3. 发表评论功能
    4. 删除评论功能
    5. 没有更多评论的处理
*/
class App extends 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>
          <button>清空评论</button>
        </div>
        <ul>
          <li>
            <h3>评论人:刘德华</h3>
            <p>评论内容:冰雨</p>
            <button>删除</button>
          </li>
        </ul>
        <div className="no-comment">暂无评论</div>
      </div>
    )
  }
}

// 幽灵节点:节点不会渲染任何的内容,跟 vue 里面的 template 标签一样
const element = (
    <React.Fragment>
        <App></App>
    </React.Fragment>
  );
  
  // 参数1:渲染的 react 元素即虚拟 DOM
  // 参数2:需要渲染到哪个容器中
  const root = ReactDom.createRoot(document.getElementById('root'));
  root.render(element);

先来看一下样式吧

 

列表展示功能:

渲染评论列表(列表渲染)

  • 在state中初始化评论列表数据

  • 使用数组的map方法遍历列表数据

  • 给每个li添加key属性

/**
 * 1. 导入react和react-dom
 * 2. 创建 react 元素
 * 3. 把 react 元素渲染到页面
 */
 import React from 'react';
 import ReactDom from 'react-dom/client';
 import { Component } from 'react';
 import './index.css'

/* 
  主要实现的功能:
    1. 展示评论功能
      1.1 通过 state 提供评论列表数据
      1.2 通过 map 动态渲染
    2. 清空评论功能
    3. 发表评论功能
    4. 删除评论功能
    5. 没有更多评论的处理
*/
class App extends Component {
  state = ({
    list: [
      {
        id: 1,
        name: '张三',
        content: '宝,我昨天去输液了。你知道是输的什么液吗?是想你的夜'
      },
      {
        id: 2,
        name: '李四',
        content: '哈哈,笑死!!!居然还有这种土味情话'
      },
      {
        id: 3,
        name: '王五',
        content: '我要定一个小目标,那就是先挣它一个亿!'
      },
      {
        id: 4,
        name: '赵六',
        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>
          <button>清空评论</button>
        </div>
        <ul>
          {
            this.state.list.map(item =>
              <li key={item.id}>
                <h3>评论人:{item.name}</h3>
                <p>评论内容:{item.content}</p>
                <button>删除</button>
             </li>
            )
          }
        </ul>
        <div className="no-comment">暂无评论</div>
      </div>
    )
  }
}

// 幽灵节点:节点不会渲染任何的内容,跟 vue 里面的 template 标签一样
const element = (
    <React.Fragment>
        <App></App>
    </React.Fragment>
  );
  
  // 参数1:渲染的 react 元素即虚拟 DOM
  // 参数2:需要渲染到哪个容器中
  const root = ReactDom.createRoot(document.getElementById('root'));
  root.render(element);

 

清空评论功能:

  • 给清空评论按钮注册事件

  • 清空评论列表

  • 没有更多评论的处理

 

/**
 * 1. 导入react和react-dom
 * 2. 创建 react 元素
 * 3. 把 react 元素渲染到页面
 */
 import React from 'react';
 import ReactDom from 'react-dom/client';
 import { Component } from 'react';
 import './index.css'

/* 
  主要实现的功能:
    1. 展示评论功能
      1.1 通过 state 提供评论列表数据
      1.2 通过 map 动态渲染
    2. 清空评论功能
    3. 发表评论功能
    4. 删除评论功能
    5. 没有更多评论的处理
*/
class App extends Component {
  state = ({
    list: [
      {
        id: 1,
        name: '张三',
        content: '宝,我昨天去输液了。你知道是输的什么液吗?是想你的夜'
      },
      {
        id: 2,
        name: '李四',
        content: '哈哈,笑死!!!居然还有这种土味情话'
      },
      {
        id: 3,
        name: '王五',
        content: '我要定一个小目标,那就是先挣它一个亿!'
      },
      {
        id: 4,
        name: '赵六',
        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>
          <button onClick={this.clearAll}>清空评论</button>
        </div>
        {
          // this.state.list.length === 0 ? (<div className="no-comment">暂无评论</div>) : 
          // (
          //   <ul>
          //   {
          //     this.state.list.map(item =>
          //       <li key={item.id}>
          //         <h3>评论人:{item.name}</h3>
          //         <p>评论内容:{item.content}</p>
          //         <button>删除</button>
          //     </li>
          //     )
          //   }
          //  </ul>
          // )
          // 或者下面这种做法
        }
        {
          this.renderList()
        }
      </div>
    )
  }
  // 清空评论
  clearAll = () => {
    this.setState({
      list: []
    })
  }
  // 没有更多评论的处理
  renderList() {
    if(this.state.list.length === 0) {
      return (<div className="no-comment">暂无评论</div>);
    } else {
      return (
        <ul>
        {
          this.state.list.map(item =>
            <li key={item.id}>
              <h3>评论人:{item.name}</h3>
              <p>评论内容:{item.content}</p>
              <button>删除</button>
          </li>
          )
        }
       </ul>
      )
    }
  }
}

// 幽灵节点:节点不会渲染任何的内容,跟 vue 里面的 template 标签一样
const element = (
    <React.Fragment>
        <App></App>
    </React.Fragment>
  );
  
  // 参数1:渲染的 react 元素即虚拟 DOM
  // 参数2:需要渲染到哪个容器中
  const root = ReactDom.createRoot(document.getElementById('root'));
  root.render(element);

 

删除评论功能:

/**
 * 1. 导入react和react-dom
 * 2. 创建 react 元素
 * 3. 把 react 元素渲染到页面
 */
 import React from 'react';
 import ReactDom from 'react-dom/client';
 import { Component } from 'react';
 import './index.css'

/* 
  主要实现的功能:
    1. 展示评论功能
      1.1 通过 state 提供评论列表数据
      1.2 通过 map 动态渲染
    2. 清空评论功能
    3. 发表评论功能
    4. 删除评论功能
    5. 没有更多评论的处理
*/
class App extends Component {
  state = ({
    list: [
      {
        id: 1,
        name: '张三',
        content: '宝,我昨天去输液了。你知道是输的什么液吗?是想你的夜'
      },
      {
        id: 2,
        name: '李四',
        content: '哈哈,笑死!!!居然还有这种土味情话'
      },
      {
        id: 3,
        name: '王五',
        content: '我要定一个小目标,那就是先挣它一个亿!'
      },
      {
        id: 4,
        name: '赵六',
        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>
          <button onClick={this.clearAll}>清空评论</button>
        </div>
        {
          this.renderList()
        }
      </div>
    )
  }
  // 清空评论
  clearAll = () => {
    this.setState({
      list: []
    })
  }
  // 没有更多评论的处理
  renderList() {
    if(this.state.list.length === 0) {
      return (<div className="no-comment">暂无评论</div>);
    } else {
      return (
        <ul>
        {
          this.state.list.map(item =>
            <li key={item.id}>
              <h3>评论人:{item.name}</h3>
              <p>评论内容:{item.content}</p>
              {
                // 传参写法:
                  // 写法1:<button onClick={() => this.del(item.id)}>删除</button>
                  // 写法2:<button onClick={this.del.bind(this, item.id)}>删除</button>
              }
              <button onClick={this.del.bind(this, item.id)}>删除</button>
          </li>
          )
        }
       </ul>
      )
    }
  }
  // 删除评论功能
  del = (id) => {
    // console.log(id);
    this.setState({
      list: this.state.list.filter(item => item.id !== id)
    })
  }
}

// 幽灵节点:节点不会渲染任何的内容,跟 vue 里面的 template 标签一样
const element = (
    <React.Fragment>
        <App></App>
    </React.Fragment>
  );
  
// 参数1:渲染的 react 元素即虚拟 DOM
// 参数2:需要渲染到哪个容器中
const root = ReactDom.createRoot(document.getElementById('root'));
root.render(element);

 

发表评论功能 :

获取评论信息,评论人和评论内容(受控组件)

  • 使用受控组件的方式获取评论数据

发表评论,更新评论列表(更新状态)

  • 给comments增加一条数据

边界处理

  • 清空内容

  • 判断非空

/**
 * 1. 导入react和react-dom
 * 2. 创建 react 元素
 * 3. 把 react 元素渲染到页面
 */
 import React from 'react';
 import ReactDom from 'react-dom/client';
 import { Component } from 'react';
 import './index.css'

/* 
  主要实现的功能:
    1. 展示评论功能
      1.1 通过 state 提供评论列表数据
      1.2 通过 map 动态渲染
    2. 清空评论功能
    3. 发表评论功能
    4. 删除评论功能
    5. 没有更多评论的处理
*/
class App extends Component {
  state = ({
    list: [
      {
        id: 1,
        name: '张三',
        content: '宝,我昨天去输液了。你知道是输的什么液吗?是想你的夜'
      },
      {
        id: 2,
        name: '李四',
        content: '哈哈,笑死!!!居然还有这种土味情话'
      },
      {
        id: 3,
        name: '王五',
        content: '我要定一个小目标,那就是先挣它一个亿!'
      },
      {
        id: 4,
        name: '赵六',
        content: '嚯哟,您这小目标可真是够小的,祝早日实现!!!'
      }
    ],
    name: '',
    content: ''
  })
  render() {
    return (
      <div className="app">
        <div>
          <input className="user" type="text" placeholder="请输入评论人" value={this.state.name} onChange={this.handleChange} name="name" />
          <br />
          <textarea
            className="content"
            cols="30"
            rows="10"
            placeholder="请输入评论内容"
            value={this.state.content}
            onChange={this.handleChange}
            name="content"
          />
          <br />
          <button onClick={this.add}>发表评论</button>
          <button onClick={this.clearAll}>清空评论</button>
        </div>
        {
          this.renderList()
        }
      </div>
    )
  }
  // 清空评论
  clearAll = () => {
    this.setState({
      list: []
    })
  }
  // 没有更多评论的处理
  renderList() {
    if(this.state.list.length === 0) {
      return (<div className="no-comment">暂无评论</div>);
    } else {
      return (
        <ul>
        {
          this.state.list.map(item =>
            <li key={item.id}>
              <h3>评论人:{item.name}</h3>
              <p>评论内容:{item.content}</p>
              <button onClick={this.del.bind(this, item.id)}>删除</button>
          </li>
          )
        }
       </ul>
      )
    }
  }
  // 删除评论功能
  del = (id) => {
    // console.log(id);
    this.setState({
      list: this.state.list.filter(item => item.id !== id)
    })
  }
  // 发表评论功能
  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({
      [name]: value
    })
  }
  add = () => {
    const { name, content, list } = this.state;
    // 当 name 或者 content 没有值
    if(!name || !content){
      return alert('信息不完整!');
    }
    // 添加评论
    this.setState({
      list: [{id: Date.now(), name: name, content: content} ,...list],
      name: '',
      content: '' 
    })
  }
}

// 幽灵节点:节点不会渲染任何的内容,跟 vue 里面的 template 标签一样
const element = (
    <React.Fragment>
        <App></App>
    </React.Fragment>
  );
  
// 参数1:渲染的 react 元素即虚拟 DOM
// 参数2:需要渲染到哪个容器中
const root = ReactDom.createRoot(document.getElementById('root'));
root.render(element);

 

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
React实现列表图片的懒加载,我们可以结合使用 `react-lazyload` 库和 `Intersection Observer API`。以下是基于这两个工具的实现步骤: 1. 首先,安装 `react-lazyload` 库。 ```bash npm install react-lazyload ``` 2. 在列表组件中引入 `react-lazyload` 组件,并使用 `Intersection Observer API` 监听图片是否进入可视区域。 ```jsx import React from 'react'; import LazyLoad from 'react-lazyload'; const ListItem = ({ imageUrl, altText }) => { return ( <LazyLoad> <img src={imageUrl} alt={altText} /> </LazyLoad> ); }; const ListComponent = ({ items }) => { return ( <ul> {items.map((item) => ( <li key={item.id}> <ListItem imageUrl={item.imageUrl} altText={item.altText} /> </li> ))} </ul> ); }; export default ListComponent; ``` 在上述代码中,我们使用 `react-lazyload` 组件包裹了 `<img>` 元素,并将图片的地址和替代文本作为属性传递给子组件 `ListItem`。当图片进入可视区域时,`react-lazyload` 会自动加载图片。 3. 在父组件中使用 `ListComponent`,并传递图片数据给列表组件。 ```jsx import React from 'react'; import ListComponent from './ListComponent'; const App = () => { const items = [ { id: 1, imageUrl: 'image1.jpg', altText: 'Image 1' }, { id: 2, imageUrl: 'image2.jpg', altText: 'Image 2' }, { id: 3, imageUrl: 'image3.jpg', altText: 'Image 3' }, // 更多图片数据 ]; return ( <div> <h1>List of Images</h1> <ListComponent items={items} /> </div> ); }; export default App; ``` 在父组件中,我们创建了一个包含图片数据的数组,并将其传递给列表组件 `ListComponent`。列表组件会根据传递的数据生成相应的图片项。 通过以上步骤,我们可以在 React实现列表图片的懒加载。 `react-lazyload` 库会自动处理图片的加载,只有当图片进入可视区域时才进行加载,从而提升页面性能和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白小白从不日白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值