React小书学习笔记 —— 实战分析:评论功能(四)

前言

学习前端一小步,迈向成功一大步!本专栏主要记录学习前端React框架的一些个人心得,分享一些实战教学,如有不足,欢迎交流讨论。React框架的入门教学强推胡子大哈React小书,简单易懂还有代码实战。还等什么?让我们开始本篇的前端学习之旅,欢迎各位入坑前端!

实战分析:评论功能(四)

参考教程:React小书–第25节(实战分析:评论功能(四))
教程作者:胡子大哈
参考链接:React小书
本文搭配原文教程食用,风味更佳~!


本篇重点

本篇是对 React 小书内代码实战过程中遇到的一些疑难点做的解释性帖子。因此不注重于代码的连贯性,代码按照 React 小书介绍排布,将针对具体细节做深入阐述。

自动聚焦到评论框

React 小书代码

1
2
3
4
5
6
7
8
render() {
...
<textarea
ref={(textarea) => {this.textarea = textarea}}
value={this.state.content}
onChange={this.handleContentChange.bind(this)} />
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CommentInput extends Component {
static propTypes = {
onSubmit: PropTypes.func
}

constructor () {
super()
this.state = {
username: '',
content: ''
}
}

componentDidMount () {
this.textarea.focus()
}
...

侧重点

  • 学会用 ref 属性调用 DOM 元素的 API
  • componentDidMount() 生命周期使用
  • PropTypes 限制输入参数类型
  • .focus()

代码编写思路

  1. 给标签添加 ref 属性值
  2. componentDidMount() 中调用 .focus(),确保组件挂载完成后聚焦光标到组件。

实战填坑

  1. <textarea ref={(textarea)=>{this.textarea=textarea}} value={this.state.content} onChange={this.handleContentChange.bind(this)} /> 中,this指的是什么?ref传的形参是什么?(textarea)可以变为其他值吗,比如(aaa)=>{this.textarea=aaa}onChange监听函数是什么?
  • this指的是什么? 请参考JavaScript 的 this 原理是什么?仔细研读,此处不知道理解的对不对,暂且记录一下:首先this是在箭头函数里的,箭头函数的this取决于它的上级调用对象,其上级为render()的函数调用,而render()调用的主体是 class CommentInput 类,因此,this 指向的是该类,即 CommentInput 组件,因此this.state; this.textarea就都很好解释了,其实就是组件类下的一些属性。
  • ref传的形参是什么? ref传入的是该属性所对应标签对象的 DOM 元素,这里指的是 textarea 输入框。
  • (textarea)可以变为其他值吗,比如(aaa)=>{this.textarea=aaa} 可以,()内的 textarea 只是一个形参名称,其实际值为 textarea 的 DOM 节点。
  • onChange监听函数是什么? 简要了解可参考JavaScript 中常见HTML事件onChange事件监听一个域的内容是否发生改变,在改变时触发绑定的函数,即触发handleContentChange()。在此重点讲一下 event对象和事件监听的关系,参考HTML DOM Event 对象,以下是我当前的理解:event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。但是我们如何去用这些状态呢?这就要靠 onClick,onChange等事件句柄监听 event 对象状态,在状态发生相应变化是触发绑定的函数,那么显而易见,所触发的函数必然接收了该事件的状态,即 event 对象,每个事件监听函数都会有一个形参 event (例如handleClick(event)),注意我们提及 event 它是一个对象,对象则必然有它对应的属性,结合HTML DOM Event 对象,可查到 event 对象对应的属性值,其中 event.target,event.currentTarget目前我用的比较多。
  1. propTypes的使用。
    大小写很容易搞混,这里要重点关注一下,按照规范来写。
  • 首先是prop-types的引入,代码为import PropTypes from 'prop-types'
  • 其次是静态对象声明,因为是一个变量,所以用驼峰命名法,代码为static propTypes = {}
  • 内部是对参数的类型限制,调用PropTypes,因为PropTypes'prop-types'中的一个类,所以开头是大写的,后面跟类型属性。
  1. .foucus()作用
    focus() 方法用于为 checkbox 赋予焦点。语法checkboxObject.focus()
    拓展:移开 checkbox 的焦点用 blur() 方法,语法checkboxObject.blur()

持久化用户名

React 小书代码

1
2
3
4
5
6
...
<input
value={this.state.username}
onBlur={this.handleUsernameBlur.bind(this)}
onChange={this.handleUsernameChange.bind(this)} />
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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)
}
...

侧重点

  • LocalStorage浏览器本地存储的使用
  • onBlur() 事件监听句柄
  • handlexxx 事件监听函数
  • componentWillMount() 生命周期

代码编写思路

  1. 通过onBlur()事件句柄绑定一个监听函数handleUsernameChange,当event事件状态失焦时,触发监听函数。
  2. 编写监听函数handleUsernameChange,接收事件状态 (即 event 对象),通过对象属性获取触发事件的目标节点,这里应该指向了<textarea />,因此通过.value将文本框内值取出,传给私有函数。
  3. 编写私有函数,通过localStorage.setItem('key',value)将值存入浏览器本地空间。

实战填坑

  1. onBlur()是什么?event是什么?
    参照“自动聚焦到评论框”实战填坑的第一问。

  2. localStorage的作用和使用方法。
    参照localStorage使用
    localStorage 作用:前提-在HTML5中实现。 主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。

    localStorage 优势:
    拓展了cookie的4K限制;
    可以将第一次请求的数据直接存储到本地,这个相当于一个5M大小的针对于前端页面的数据库,相比于cookie可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的;
    localStorage与sessionStorage的唯一一点区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空;

localStorage 两种使用:

  • localStorage.getItem('key'):获取指定key字段本地存储的值。 注意,我这里特别强调了字段,即接收的 key 参数是个字符,需要' '包裹。
  • localStorage.setItem('key',value):将value存储到key字段。 同理,这里key也是字符,value是数据。

.getItem()方法主要是从浏览器本地存储中获取相应 key 的值 value。
.setItem()方法主要是将值存储到本地存储中的指定 key 字段中,若没有 key 则由本地存储创建一个空的 key。

localStorage 使用实例:

1
2
3
4
5
6
在A页面中先存储:
var imgs = obj_mainform.archivesId //声明个变量存储下数据
localStorage.setItem('key',imgs); //将变量imgs存储到name字段

在B页面中使用:
var naid = localStorage.getItem("key"); //获取指定key本地存储的值
  1. handleUsernameBlur (event) {this._saveUsername(event.target.value)}中,为什么要用this调用类中的私有方法?
    首先,我们需要知道的一点是,对于这个函数来说,我将 this. 去掉对整个过程没有任何的影响。那我们为什么还要去“多此一举”加入this呢?这就涉及到了 JS 的编程思想,原先 JS 语言提出的过程中,主要是面向函数的,即函数内调用函数,内部函数是通过向上查找发现的,随着 ES6 的提出,JS 的编程思想逐渐从面向函数向面向对象转变,此处的this即指向了类这个对象(JS 类的概念是在ES6中提出的)。所以我们在理解的时候可以认为:类内部函数的调用需要用this是目前一个通用的写法。
    我们理解了上述的思想后,再回过头来看这段代码:
    1
    2
    3
    <input
    value={this.state.username}
    onBlur={this.handleUsernameBlur.bind(this)}/>
    第二行,this.handleUsernameBlur是类内函数调用的一个通用写法,所以 this 指的就是类(准确来说是类的实例),那有人就问,既然都指向类了,为什么还要.bind(this)呢?前面提到的this.xxx是类内调用函数的通用写法,虽然函数写在了类内,但它并没有与类进行一个绑定,当触发该事件监听函数时,是在全局环境下运行handleUsernameBlur(),即 windows 对象调用的该函数,this 就指向了 windows,为了让类内函数在触发时指向类,就需要对它做一个绑定。
    都谈到这了,那么就说一下第一行的this的指向,this 永远指向调用包含自身(this本身)的函数对应的对象。那么是什么函数调用了this.state.username呢?答案是render(),或者可以理解为是CommentInput.render(),那么显而易见这个对象,也就是this所指向的是 CommentInput。