React.js 小书 Lesson25 - 实战分析:评论功能(四)
- 作者:胡子大哈
- 原文链接:http://huziketang.com/books/react/lesson25
- 转载请注明出处,保留原文链接和作者信息。
(本文未审核)
目前为止,第二阶段知识已经基本介绍完,我们已经具备了项目上手实战必备的 React.js 知识,现在可以把这些知识应用起来。接下来是实战环节,我们会继续上一阶段的例子,把评论功能做得更加复杂一点。
我们在上一阶段的评论功能基础上加上以下功能需求:
- 页面加载完成自动聚焦到评论输入框。
- 把用户名持久化,存放到浏览器的 LocalStorage 中。页面加载时会把用户名加载出来显示到输入框,用户就不需要重新输入用户名了。
- 把已经发布的评论持久化,存放到浏览器的 LocalStorage 中。页面加载时会把已经保存的评论加载出来,显示到页面的评论列表上。
- 评论显示发布日期,如“1 秒前”,”30 分钟前”,并且会每隔 5 秒更新发布日期。
- 评论可以被删除。
- 类似 Markdown 的行内代码块显示功能,用户输入的用 `` 包含起来的内容都会被处理成用
<code>
元素包含。例如输入 `console.log` 就会处理成<code>console.log</code>
再显示到页面上。
大家可以在原来的第一阶段代码的基础上进行修改,第一、二阶段评论功能代码可以在这里找到: react-naive-book-examples。可以直接使用最新的样式文件 index.css 覆盖原来的 index.css。
接下来可以分析如何利用第二阶段的知识来构建这些功能,在这个过程里面可能会穿插一些小技巧,希望对大家有用。我们回顾一下这个页面的组成:
我们之前把页面分成了四种不同的组件:分别是 CommentApp
、CommentInput
、CommentList
、Comment
。我们开始修改这个组件,把上面的需求逐个完成。
自动聚焦到评论框
这个功能是很简单的,我们需要获取 textarea
的 DOM 元素然后调用 focus()
API 就可以了。我们给输入框元素加上 ref
以便获取到 DOM 元素,修改 src/CommentInput.js
文件:
...
<textarea
ref={(textarea) => this.textarea = textarea}
value={this.state.content}
onChange={this.handleContentChange.bind(this)} />
...
组件挂载完以后完成以后就可以调用 this.textarea.focus()
,给 CommentInput
组件加上 ComponentDidMount
生命周期:
class CommentInput extends Component {
static propTypes = {
onSubmit: PropTypes.func
}
constructor () {
super()
this.state = {
username: '',
content: ''
}
}
componentDidMount () {
this.textarea.focus()
}
...
这个功能就完成了。现在体验还不是很好,接下来我们把用户名持久化一下,体验就会好很多。
大家可以注意到我们给原来的 props.onSubmit
参数加了组件参数验证,在这次实战案例中,我们都会给评论功能的组件加上 propTypes
进行参数验证,接下来就不累述。
持久化用户名
用户输入用户名,然后我们把用户名保存到浏览器的 LocalStorage 当中,当页面加载的时候再从 LocalStorage 把之前保存的用户名显示到用户名输入框当中。这样用户就不用每次都输入用户名了,并且评论框是自动聚焦的,用户的输入体验就好很多。
我们监听用户名输入框失去焦点的事件 onBlur
:
...
<input
value={this.state.username}
onBlur={this.handleUsernameBlur.bind(this)}
onChange={this.handleUsernameChange.bind(this)} />
...
在 handleUsernameBlur
中我们把用户的输入内容保存到 LocalStorage 当中:
class CommentInput extends Component {
constructor () {
super()
this.state = {
username: '',
content: ''
}
}
componentDidMount () {
this.textarea.focus()
}
_saveUsername (username) {
localStorage.setItem('username', username)
}
handleUsernameBlur (event) {
this._saveUsername(event.target.value)
}
...
在 handleUsernameBlur
中我们把用户输入的内容传给了 _saveUsername
私有方法(所有私有方法都以 _
开头)。_saveUsername
会设置 LocalStorage 中的 username
字段,用户名就持久化了。这样就相当于每当用户输入完用户名以后(输入框失去焦点的时候),都会把用户名自动保存一次。
输入用户名,然后到浏览器里里面看看是否保存了:
然后我们组件挂载的时候把用户名加载出来。这是一种数据加载操作,我们说过,不依赖 DOM 操作的组件启动的操作都可以放在 componentWillMount
中进行,所以给 CommentInput
添加 componentWillMount
的组件生命周期:
...
componentWillMount () {
this._loadUsername()
}
_loadUsername () {
const username = localStorage.getItem('username')
if (username) {
this.setState({ username })
}
}
_saveUsername (username) {
localStorage.setItem('username', username)
}
...
componentWillMount
会调用 _loadUsername
私有方法,_loadUsername
会从 LocalStorage 加载用户名并且 setState
到组件的 state.username
中。那么组件在渲染的时候(render
方法)挂载的时候就可以用上用户名了。
这样体验就好多了,刷新页面,不需要输入用户名,并且自动聚焦到了输入框。我们 1、 2 需求都已经完成。
小贴士
这里插入一些小贴示,大家可以注意到我们组件的命名和方法的摆放顺序其实有一定的讲究,这里可以简单分享一下个人的习惯,仅供参考。
组件的私有方法都用 _
开头,所有事件监听的方法都用 handle
开头。把事件监听方法传给组件的时候,属性名用 on
开头。例如:
<CommentInput
onSubmit={this.handleSubmitComment.bind(this)} />
这样统一规范处理事件命名会给我们带来语义化组件的好处,监听(on
)CommentInput
的 Submit
事件,并且交给 this
去处理(handle
)。这种规范在多人协作的时候也会非常方便。
另外,组件的内容编写顺序如下:
- static 开头的类属性,如
defaultProps
、propTypes
。 - 构造函数,
constructor
。 - getter/setter(还不了解的同学可以暂时忽略)。
- 组件生命周期。
_
开头的私有方法。- 事件监听方法,
handle*
。 render*
开头的方法,有时候render()
方法里面的内容会分开到不同函数里面进行,这些函数都以render*
开头。render()
方法。
如果所有的组件都按这种顺序来编写,那么维护起来就会方便很多,多人协作的时候别人理解代码也会一目了然。
因为第三方评论工具有问题,对本章节有任何疑问的朋友可以移步到 React.js 小书的论坛 发帖,我会回答大家的疑问。
React.js 小书 Lesson25 - 实战分析:评论功能(四)的更多相关文章
- React.js 小书 Lesson16 - 实战分析:评论功能(三)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson16 转载请注明出处,保留原文链接和作者信息. 接下来的代码比较顺理成章了.修改 Commen ...
- React.js 小书 Lesson14 - 实战分析:评论功能(一)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson14 转载请注明出处,保留原文链接和作者信息. 课程到这里大家已经掌握了 React.js 的 ...
- React.js 小书 Lesson26 - 实战分析:评论功能(五)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson26 转载请注明出处,保留原文链接和作者信息. (本文未审核) 持久化评论 同样地,可以通过类 ...
- React.js 小书 Lesson15 - 实战分析:评论功能(二)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson15 转载请注明出处,保留原文链接和作者信息. 上一节我们构建了基本的代码框架,现在开始完善其 ...
- React.js 小书 Lesson27 - 实战分析:评论功能(六)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson27 转载请注明出处,保留原文链接和作者信息. (本文未审核) 删除评论 现在发布评论,评论不 ...
- 【React.js小书】动手实现 React-redux(五):Provider - 方志
我们要把 context 相关的代码从所有业务组件中清除出去,现在的代码里面还有一个地方是被污染的.那就是 src/index.js 里面的 Index: 1234567891011121314151 ...
- React.js 小书介绍
React.js 小书 Github 关于作者 这是一本关于 React.js 的小书. 因为工作中一直在使用 React.js,也一直以来想总结一下自己关于 React.js 的一些知识.经验.于是 ...
- React.js 小书 Lesson20 - 更新阶段的组件生命周期
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson20 转载请注明出处,保留原文链接和作者信息. 从之前的章节我们了解到,组件的挂载指的是将组件 ...
- React.js 小书 Lesson24 - PropTypes 和组件参数验证
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson24 转载请注明出处,保留原文链接和作者信息. 我们来了到了一个非常尴尬的章节,很多初学的朋友 ...
随机推荐
- 【C#】事件
前言:CLR事件模式建立在委托的基础上,委托说调用回调方法的一种类型安全的方式. 我个人觉得事件本质就是委托,所以把委托弄清楚,只要知道事件基本语法就会使用了(如果说到线程安全,我个人觉得这个应该和线 ...
- Java50道经典习题-程序1 不死神兔
题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少? 分析:假如:1月1日有1对兔子,根据题目“从出生后 ...
- 解决Struts2拦截器的对于参数传递无效问题
今天做项目时,使用拦截器对用户权限检查.拦截器本身没有问题,可是实现权限拦截,但是传递的参数全部都无效了.搞了很久,由于对拦截器的内部机制不是特别熟悉,所以重新研读了一下Struts2的拦截器.找到了 ...
- mvc - Authorize授权
from : http://www.cnblogs.com/asks/p/4372783.html http://www.cnblogs.com/myindex/p/5479428.html
- 如何提高scrapy的爬取效率
提高scrapy的爬取效率 增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增加.在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置 ...
- Tomcat入门级小白教程
Tomcat 类似与一个apache的扩展型,属于apache软件基金会的核心项目,属于开源的轻量级Web应用服务器,是开发和调试JSP程序的首选,主要针对Jave语言开发的网页代码进行解析,Tomc ...
- Nginx+Apache动静分离
Nginx的静态处理能力很强,但是动态处理能力不足,因此,在企业中常用动静分离技术.动静分离技术其实是采用代理的方式,在server{}段中加入带正则匹配的location来指定匹配项 针对PHP的动 ...
- P5030 长脖子鹿放置 最小割
$ \color{#0066ff}{ 题目描述 }$ 如图所示,西洋棋的"长脖子鹿",类似于中国象棋的马,但按照"目"字攻击,且没有中国象棋"别马腿& ...
- 2. Javscript学习笔记——引用类型
2. 引用类型 2.1 Object类型 Object 是一个基础类型,其他所有类型都从 Object 继承了基本的行为. 对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象 ...
- [转] HBase 深入浅出
[From] https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-bigdata-hbase/index.html HBase ...