React系列實戰篇:留言功能(三)

快來加入咱們吧!

"小和山的菜鳥們",爲前端開發者提供技術相關資訊以及系列基礎文章。爲更好的用戶體驗,請您移至咱們官網小和山的菜鳥們 ( xhs-rookies.com/ ) 進行學習,及時獲取最新文章。css

"Code tailor" ,若是您對咱們文章感興趣、或是想提一些建議,微信關注 「小和山的菜鳥們」 公衆號,與咱們取的聯繫,您也能夠在微信上觀看咱們的文章。每個建議或是贊同都是對咱們極大的鼓勵!前端

實戰案例(三):留言功能改版

咱們此次學了一些新內容,咱們須要將以前的改版。react

新增點贊功能

若是咱們須要對某個評論進行點贊怎麼辦呢?git

若是按照上次那樣子經過某個屬性傳入控制是否顯示點贊,這是能夠的。github

咱們上次抽象了 InputCompoent 輸入框組件和 EvaluateCompoent 列表展現組件這兩個組件,此次咱們須要新增一個 comment 組件來完成點贊功能。web

不須要的組件去除微信

上次咱們將 InputCompoent 輸入框組件和 EvaluateCompoent 列表展現組件抽象出來放置於 component 文件夾中,咱們先將這兩個組件直接放置於App.js中。(爲了直觀,咱們先這兩個已經抽象好的給直接放置於 App.js 中)markdown

咱們只須要抽象一個comment組件,給上次的EvaluateCompoent列表展現組件加上咱們的點贊功能,每一個列表中的評論咱們均可以進行點贊。oop

所以咱們將首頁App.js修改成以下:學習

import React, { PureComponent } from 'react'
import Comment from './comment'
import './App.css'

class App extends PureComponent {
  constructor() {
    super()
    this.state = {
      title: 'Hello React',
      desc: '你知道有這麼一個團隊嗎?他們懷揣夢想,艱苦奮鬥,做爲一羣大學生菜鳥,放棄了平時娛樂的時間,選擇一塊兒學習,一塊兒成長,將平時學習的筆記,心得總結爲文章,目的很簡單,但願能夠幫助向他們同樣的菜鳥們?你想了解更多嗎?快搜索微信公衆號:小和山的菜鳥們,加入他們吧!',
      comments: [
        {
          headPortrait: 'https://xhs-rookies.com/img/rookie-icon.png',
          time: new Date(2021, 4, 14, 21, 2, 30),
          nickName: '小菜鳥',
          detail: '這是一個即將推出系列文章的團隊,咱們一塊兒期待他們的做品吧!',
          liked: true,
          likeNum: 23,
        },
      ],
      text: '',
    }
  }

  render() {
    const { title, desc, comments, text } = this.state
    return (
      <div className="App"> <h2>{title}</h2> <div className="desc">{desc}</div> <div style={{ width: '100%' }}> <p className="commentsTitle">評論</p> {comments.map((item, index) => { return ( <Comment key={item.time.getTime()} changeLike={() => { this.changeLike(index) }} {...item} /> ) })} </div> <div className="newComment"> <div style={{ display: 'flex' }}> <img src="https://xhs-rookies.com/img/rookie-icon.png" className="" alt="" /> <textarea value={text} onChange={(e) => this.changeText(e)} placeholder="請輸入評論" /> </div> <div className="submit" onClick={() => { this.addComment() }} > 發表 </div> </div> </div>
    )
  }

  changeText(e) {
    this.setState({ text: e.target.value })
  }

  changeLike(index) {
    let newArray = [...this.state.comments]
    let newItem = { ...newArray[index] }
    if (newItem.liked) {
      newItem.liked = false
      newItem.likeNum -= 1
    } else {
      newItem.liked = true
      newItem.likeNum += 1
    }
    newArray[index] = newItem
    this.setState({
      comments: newArray,
    })
  }

  addComment() {
    if (!this.state.text) {
      alert('請輸入留言內容')
      return
    }
    let detail = this.state.text
    this.setState({ text: '' })
    let newComment = {
      headPortrait: 'https://xhs-rookies.com/img/rookie-icon.png',
      time: new Date(),
      nickName: '小菜鳥',
      detail,
      liked: false,
      likeNum: 0,
    }
    this.setState({
      comments: [newComment, ...this.state.comments],
    })
  }
}

App.propTypes = {}

export default App
複製代碼

組合 comment 組件

點贊功能

首先咱們須要考慮這個組件須要什麼功能。

除了上次抽象出來的:

須要有頭像、時間、名字、內容這幾個外,咱們還須要一個點贊按鈕,這個按鈕點擊一下變成紅色,而且數字加一,再次點擊顏色從新改成灰色,而且數字減一。

<span className={'likeBox ' + (liked ? 'like' : 'unlike')} onClick={() => changeLike()}>
  <span className="icon"> </span>
  <span>{!!likeNum && likeNum}</span>
</span>
複製代碼

一個 span 用於存放點贊圖標,一個用於顯示點讚的數字。

數據檢測

此次咱們數據變得更加多了,外面傳給該組件的數據愈來愈多以後,咱們如何判斷,或是說保證給進來內容是正確的呢?(是否爲空?)

咱們採用propType進行內容檢測,若是出現錯誤,能夠快速幫咱們定位錯誤並進行修改。

Comment.propTypes = {
  nickName: PropTypes.string.isRequired,
  time: PropTypes.object.isRequired,
  headPortrait: PropTypes.string.isRequired,
  detail: PropTypes.string.isRequired,
  liked: PropTypes.bool.isRequired,
  likeNum: PropTypes.number.isRequired,
  changeLike: PropTypes.func.isRequired,
}
複製代碼

最終組合

那咱們將以前的EvaluateCompoent列表展現組件加上點贊功能,在將數據檢測功能添加進去,咱們的 comment 組件就完成了。

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import './comment.css'

class Comment extends PureComponent {
  render() {
    const { nickName, time, headPortrait, detail, liked, likeNum, changeLike } = this.props
    return (
      <div className="comment"> <div className="info"> <img src={headPortrait} alt="頭像" /> <div> <p className="nickname">{nickName}</p> <p className="time">{this.getTime(time)}</p> </div> </div> <div className="detail" style={{ marginBottom: '10px' }}> {detail} </div> <div className="toolBox"> <span className={'likeBox ' + (liked ? 'like' : 'unlike')} onClick={() => changeLike()}> <span className="icon"> </span> <span>{!!likeNum && likeNum}</span> </span> <span className="share icon"> </span> </div> </div>
    )
  }

  getTime(time) {
    const year = time.getFullYear()
    const month = time.getMonth() + 1
    const day = time.getDate()
    const hour = String(time.getHours()).padStart(2, '0')
    const minute = String(time.getMinutes()).padStart(2, '0')
    const second = String(time.getSeconds()).padStart(2, '0')
    return `${year}.${month}.${day} ${hour}:${minute}:${second}`
  }
}

Comment.propTypes = {
  nickName: PropTypes.string.isRequired,
  time: PropTypes.object.isRequired,
  headPortrait: PropTypes.string.isRequired,
  detail: PropTypes.string.isRequired,
  liked: PropTypes.bool.isRequired,
  likeNum: PropTypes.number.isRequired,
  changeLike: PropTypes.func.isRequired,
}

export default Comment
複製代碼

源碼地址

項目 github 地址

直接預覽

咱們建議採用 codesanbox 的形式能夠在線快速訪問當前實戰案例。

CodeSandBox

下節預告

下節中咱們將講述使用React中State的相關信息,深刻理解 setState 方法以及一些相關內容。敬請期待!

相關文章
相關標籤/搜索