"小和山的菜鸟们",为前端开发者提供技术相关资讯以及系列基础文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 ( 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
复制代码
首先咱们须要考虑这个组件须要什么功能。
除了上次抽象出来的:
须要有头像、时间、名字、内容这几个外,咱们还须要一个点赞按钮,这个按钮点击一下变成红色,而且数字加一,再次点击颜色从新改成灰色,而且数字减一。
<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
复制代码
咱们建议采用 codesanbox
的形式能够在线快速访问当前实战案例。
下节中咱们将讲述使用React中State的相关信息,深刻理解 setState 方法以及一些相关内容。敬请期待!