React.js 小书 Lesson27 - 实战分析:评论功能(六)

本文作者:胡子大哈
本文原文:http://huziketang.com/books/react/lesson27

转载请注明出处,保留原文链接以及作者信息

在线阅读:http://huziketang.com/books/react


{%raw%}

删除评论

现在发布评论,评论不会消失,评论越来越多并不是什么好事。所以我们给评论组件加上删除评论的功能,这样就可以删除不想要的评论了。修改 src/Comment.jsrender 方法,新增一个删除按钮:

...render () {const { comment } = this.propsreturn (<div className='comment'><div className='comment-user'><span className='comment-username'>{comment.username}</span>:</div><p>{comment.content}</p><span className='comment-createdtime'>{this.state.timeString}</span><span className='comment-delete'>删除</span></div>)}
... 

我们在后面加了一个删除按钮,因为 index.css 定义了样式,所以鼠标放到特定的评论上才会显示删除按钮,让用户体验好一些。

我们知道评论列表数据是放在 CommentApp 当中的,而这个删除按钮是在 Comment 当中的,现在我们要做的事情是用户点击某条评论的删除按钮,然后在 CommentApp 中把相应的数据删除。但是 CommentAppComment 的关系是这样的:

CommentCommentApp 之间隔了一个 CommentListComment 无法直接跟 CommentApp 打交道,只能通过 CommentList 来转发这种删除评论的消息。修改 Comment 组件,让它可以把删除的消息传递到上一层:

class Comment extends Component {static propTypes = {comment: PropTypes.object.isRequired,onDeleteComment: PropTypes.func,index: PropTypes.number}
...handleDeleteComment () {if (this.props.onDeleteComment) {this.props.onDeleteComment(this.props.index)}}render () {...<spanonClick={this.handleDeleteComment.bind(this)}className='comment-delete'>删除</span></div>)}

现在在使用 Comment 的时候,可以传入 onDeleteCommentindex 两个参数。index 用来标志这个评论在列表的下标,这样点击删除按钮的时候我们才能知道你点击的是哪个评论,才能知道怎么从列表数据中删除。用户点击删除会调用 handleDeleteComment ,它会调用从上层传入的 props. onDeleteComment 函数告知上一层组件删除的消息,并且把评论下标传出去。现在修改 src/CommentList.js 让它把这两个参数传进来:

class CommentList extends Component {static propTypes = {comments: PropTypes.array,onDeleteComment: PropTypes.func}static defaultProps = {comments: []}handleDeleteComment (index) {if (this.props.onDeleteComment) {this.props.onDeleteComment(index)}}render() {return (<div>{this.props.comments.map((comment, i) =><Commentcomment={comment}key={i}index={i}onDeleteComment={this.handleDeleteComment.bind(this)} />)}</div>)}
}

当用户点击按钮的时候,Comment 组件会调用 props.onDeleteComment,也就是 CommentListhandleDeleteComment 方法。而 handleDeleteComment 会调用 CommentList 所接受的配置参数中的 props.onDeleteComment,并且把下标传出去。

也就是说,我们可以在 CommentAppCommentList 传入一个 onDeleteComment 的配置参数来接受这个删除评论的消息,修改 CommentApp.js

...handleDeleteComment (index) {console.log(index)}render() {return (<div className='wrapper'><CommentInput onSubmit={this.handleSubmitComment.bind(this)} /><CommentListcomments={this.state.comments}onDeleteComment={this.handleDeleteComment.bind(this)} /></div>)}
}
...

现在点击删除按钮,可以在控制台看到评论对应的下标打印了出来。其实这就是这么一个过程:CommentList 把下标 index 传给 Comment。点击删除按钮的时候,Commentindex 传给了 CommentListCommentList 再把它传给 CommentApp。现在可以在 CommentApp 中删除评论了:

...handleDeleteComment (index) {const comments = this.state.commentscomments.splice(index, 1)this.setState({ comments })this._saveComments(comments)}
...

我们通过 comments.splice 删除特定下标的评论,并且通过 setState 重新渲染整个评论列表;当然了,还需要把最新的评论列表数据更新到 LocalStorage 中,所以我们在删除、更新以后调用了 _saveComments 方法把数据同步到 LocalStorage 中。

现在就可以愉快地删除评论了。但是,你删除评论以后 5 秒钟后就会在控制台中看到报错了:

这是因为我们忘了清除评论的定时器,修改 src/Comment.js,新增生命周期 commentWillUnmount 在评论组件销毁的时候清除定时器:

...componentWillUnmount () {clearInterval(this._timer)}
...

这才算完成了第 5 个需求。

显示代码块

用户在的输入内容中任何以 `` 包含的内容都会用 <code> 包含起来显示到页面上。<code> 这是一个 HTML 结构,需要往页面动态插入 HTML 结构我们只能用 dangerouslySetInnerHTML 了,修改 src/Comment.js,把原来 render() 函数中的:

<p>{comment.content}</p>

修改成:

<p dangerouslySetInnerHTML={{__html: this._getProcessedContent(comment.content)
}} />

我们把经过 this._getProcessedContent 处理的评论内容以 HTML 的方式插入到 <p> 元素中,this._getProcessedContent 是这样实现的:

..._getProcessedContent (content) {return content.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "'").replace(/`([\S\s]+?)`/g, '<code>$1</code>')}
...

看起来很复杂,其实前 5 行是用来处理 HTML 内容转义的,最后一行是用来插入 <code> 标签的。如果我们把用户输入的内容全部以 HTML 显示到页面上,那么就会造成跨站脚本攻击。所以前 5 个 replace 实际上是把类似于 <> 这种内容替换转义一下。而最后一行才是真正实现需求的代码,把 `` 包含的内容用 <code> 包裹起来。

输入:

这是代码块 `console.log`,这是 <h1>正常内容</h1>。

看看效果:

我们安全地完成了第 6 个需求。到目前为止,第二阶段的实战已经全部完成,你可以在这里找到完整的代码。

总结

到这里第二阶段已经全部结束,我们已经掌握了全部 React.js 实战需要的入门知识。接下来我们会学习两个相对比较高级的 React.js 的概念,然后进入 React-router 和 Redux 的世界,让它们配合 React.js 来构建更成熟的前端页面。
{%endraw%}

下一节中我们将介绍《React.js 小书 Lesson28 - 高阶组件(Higher-Order Components)》。

React.js 小书 Lesson27 - 实战分析:评论功能(六)相关推荐

  1. React.js 小书 Lesson14 - 实战分析:评论功能(一)

    React.js 小书 Lesson14 - 实战分析:评论功能(一) 本文作者:胡子大哈 本文原文:http://react.huziketang.com/blog/lesson14 转载请注明出处 ...

  2. React.js 小书 Lesson15 - 实战分析:评论功能(二)

    作者:胡子大哈 原文链接: http://huziketang.com/books/react/lesson15 转载请注明出处,保留原文链接和作者信息. 上一节我们构建了基本的代码框架,现在开始完善 ...

  3. React.js 小书 Lesson24 - PropTypes 和组件参数验证

    作者:胡子大哈 原文链接: http://huziketang.com/books/react/lesson24 转载请注明出处,保留原文链接和作者信息. 我们来了到了一个非常尴尬的章节,很多初学的朋 ...

  4. React.js 小书 Lesson12 - state vs props

    React.js 小书 Lesson12 - state vs props 本文作者:胡子大哈 本文原文:http://huziketang.com/books/react/lesson12 转载请注 ...

  5. React.js 小书 Lesson5 - React.js 基本环境安装

    React.js 小书 Lesson5 - React.js 基本环境安装 本文作者:胡子大哈 本文原文:http://huziketang.com/books/react/lesson5 转载请注明 ...

  6. React.js 小书 Lesson18 - 挂载阶段的组件生命周期(一)

    React.js 小书 Lesson18 - 挂载阶段的组件生命周期(一) 本文作者:胡子大哈 本文原文:http://huziketang.com/books/react/lesson18 转载请注 ...

  7. React.js 小书 Lesson1-2 - 前端组件化(一):从一个简单的例子讲起

    React.js 小书 Lesson1-2 - 前端组件化(一):从一个简单的例子讲起 本文作者:胡子大哈 本文原文:http://huziketang.com/books/react/lesson2 ...

  8. React.js小书总结

    (迁移自旧博客2017 08 27) 第一阶段 react的组件相当于MVC里面的View. react.js 将帮助我们将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合.嵌套,就成 ...

  9. 专访小书作者刘传君:练太极的“读书机器”

    访谈嘉宾:刘传君 刘传君,创过业.做过产品.一个爱读书,喜欢分享的程序员.先后在图灵社区出版了<HTTP小书><Git小书><Vue.js小书><Swift ...

最新文章

  1. python读取数据校验数据_Python通过Schema实现数据验证方式
  2. react取消所有请求_React Hooks中取消HTTP请求来避免内存泄漏
  3. linux服务器 32核,Intel换成AMD 32核锐龙 Linux之父体验很好
  4. 本期最新 9 篇论文,每一篇都想推荐给你 | PaperDaily #14
  5. 64位windows 7下成功配置TortoiseGit使用Github服务器
  6. Java swing中的keyListener使用事例
  7. ## CSP 201809-2 买菜(C语言)(100分)
  8. 关于YUV格式的一些总结
  9. jquery多字段筛选,极简方法
  10. Hadoop安装详细教程 单机版
  11. KVM 虚拟化技术(理论详解+实战)
  12. 有监督学习和无监督学习
  13. python导入numpy模块_Python之路-numpy模块
  14. R语言导入数据文件 (Excel文件、csv文件导入R)
  15. BootStrap富文本编辑器Summernote
  16. Yolov5(6.1)学习历险记
  17. 开展跨境电商企业需要哪些资质?
  18. 软件质量之道:PCLint之中的一个
  19. 简历中的项目经历怎么写?
  20. 数据结构:元祖、列表、字典、集合概念及区别

热门文章

  1. 微软将发布5月安全漏洞补丁 修补PPT
  2. springboot 日志问题记录
  3. 程序员做产品需要知道
  4. UITableView中发现的小技巧(不断更新)
  5. 如何管理大型呼叫中心
  6. C# params关键字
  7. 胖子哥的大数据之路(10)- 基于Hive构建数据仓库实例
  8. android 连接服务器
  9. 你离高级工程师有多远
  10. python之路6-迭代器、生成器、装饰器