react注意点
event 对象
和普通浏览器一样,事件监听函数会被自动传入一个 event
对象,这个对象和普通的浏览器 event
对象所包含的方法和属性都基本一致。不同的是 React.js 中的 event
对象并不是浏览器提供的,而是它自己内部所构建的。React.js 将浏览器原生的 event
对象封装了一下,对外提供统一的 API 和属性,这样你就不用考虑不同浏览器的兼容性问题。这个 event
对象是符合 W3C 标准( W3C UI Events )的,它具有类似于event.stopPropagation
、event.preventDefault
这种常用的方法。
我们来尝试一下,这次尝试当用户点击 h1
的时候,把 h1
的 innerHTML
打印出来:
class Title extends Component {
handleClickOnTitle (e) {
console.log(e.target.innerHTML)
} render () {
return (
<h1 onClick={this.handleClickOnTitle}>React 小书</h1>
)
}
}
再看看控制台,每次点击的时候就会打印”React 小书“。
关于事件中的 this
一般在某个类的实例方法里面的 this
指的是这个实例本身。但是你在上面的 handleClickOnTitle
中把 this
打印出来,你会看到 this
是 null
或者 undefined
。
...
handleClickOnTitle (e) {
console.log(this) // => null or undefined
}
...
这是因为 React.js 调用你所传给它的方法的时候,并不是通过对象方法的方式调用(this.handleClickOnTitle
),而是直接通过函数调用 (handleClickOnTitle
),所以事件监听函数内并不能通过 this
获取到实例。
如果你想在事件函数当中使用当前的实例,你需要手动地将实例方法 bind
到当前实例上再传入给 React.js。
class Title extends Component {
handleClickOnTitle (e) {
console.log(this)
} render () {
return (
<h1 onClick={this.handleClickOnTitle.bind(this)}>React 小书</h1>
)
}
}
bind
会把实例方法绑定到当前实例上,然后我们再把绑定后的函数传给 React.js 的 onClick
事件监听。这时候你再看看,点击 h1
的时候,就会把当前的实例打印出来:
你也可以在 bind
的时候给事件监听函数传入一些参数:
class Title extends Component {
handleClickOnTitle (word, e) {
console.log(this, word)
} render () {
return (
<h1 onClick={this.handleClickOnTitle.bind(this, 'Hello')}>React 小书</h1>
)
}
}
这种 bind
模式在 React.js 的事件监听当中非常常见,bind
不仅可以帮我们把事件监听方法中的 this
绑定到当前组件实例上;还可以帮助我们在在渲染列表元素的时候,把列表元素传入事件监听函数当中——这个将在以后的章节提及。
如果有些同学对 JavaScript 的 this
模式或者 bind
函数的使用方式不是特别了解到话,可能会对这部分内容会有些迷惑,参考博客里面的this的详解。
setState 接受函数参数
这里还有要注意的是,当你调用 setState
的时候,React.js 并不会马上修改 state。而是把这个对象放到一个更新队列里面,稍后才会从队列当中把新的状态提取出来合并到 state
当中,然后再触发组件更新。这一点要好好注意。可以体会一下下面的代码:
...
handleClickOnLikeButton () {
console.log(this.state.isLiked)
this.setState({
isLiked: !this.state.isLiked
})
console.log(this.state.isLiked)
}
...
你会发现两次打印的都是 false
,即使我们中间已经 setState
过一次了。这并不是什么 bug,只是 React.js 的 setState
把你的传进来的状态缓存起来,稍后才会帮你更新到 state
上,所以你获取到的还是原来的 isLiked
。
所以如果你想在 setState
之后使用新的 state
来做后续运算就做不到了,例如:
...
handleClickOnLikeButton () {
this.setState({ count: 0 }) // => this.state.count 还是 undefined
this.setState({ count: this.state.count + 1}) // => undefined + 1 = NaN
this.setState({ count: this.state.count + 2}) // => NaN + 2 = NaN
}
...
上面的代码的运行结果并不能达到我们的预期,我们希望 count
运行结果是 3
,可是最后得到的是 NaN
。但是这种后续操作依赖前一个 setState
的结果的情况并不罕见。
这里就自然地引出了 setState
的第二种使用方式,可以接受一个函数作为参数。React.js 会把上一个 setState
的结果传入这个函数,你就可以使用该结果进行运算、操作,然后返回一个对象作为更新 state
的对象:
...
handleClickOnLikeButton () {
this.setState((prevState) => {
return { count: 0 }
})
this.setState((prevState) => {
return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
})
this.setState((prevState) => {
return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
})
// 最后的结果是 this.state.count 为 3
}
...
这样就可以达到上述的利用上一次 setState
结果进行运算的效果。
默认配置 defaultProps
上面的组件默认配置我们是通过 ||
操作符来实现。这种需要默认配置的情况在 React.js 中非常常见,所以 React.js 也提供了一种方式 defaultProps
,可以方便的做到默认配置。
class LikeButton extends Component {
static defaultProps = {
likedText: '取消',
unlikedText: '点赞'
} constructor () {
super()
this.state = { isLiked: false }
} handleClickOnLikeButton () {
this.setState({
isLiked: !this.state.isLiked
})
} render () {
return (
<button onClick={this.handleClickOnLikeButton.bind(this)}>
{this.state.isLiked
? this.props.likedText
: this.props.unlikedText}react注意点的更多相关文章
- react组件的生命周期
写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...
- 十分钟介绍mobx与react
原文地址:https://mobxjs.github.io/mobx/getting-started.html 写在前面:本人英语水平有限,主要是写给自己看的,若有哪位同学看到了有问题的地方,请为我指 ...
- RxJS + Redux + React = Amazing!(译一)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: https:/ ...
- React 入门教程
React 起源于Facebook内部项目,是一个用来构建用户界面的 javascript 库,相当于MVC架构中的V层框架,与市面上其他框架不同的是,React 把每一个组件当成了一个状态机,组件内 ...
- 通往全栈工程师的捷径 —— react
腾讯Bugly特约作者: 左明 首先,我们来看看 React 在世界范围的热度趋势,下图是关键词“房价”和 “React” 在 Google Trends 上的搜索量对比,蓝色的是 React,红色的 ...
- 2017-1-5 天气雨 React 学习笔记
官方example 中basic-click-counter <script type="text/babel"> var Counter = React.create ...
- RxJS + Redux + React = Amazing!(译二)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...
- React在开发中的常用结构以及功能详解
一.React什么算法,什么虚拟DOM,什么核心内容网上一大堆,请自行google. 但是能把算法说清楚,虚拟DOM说清楚的聊聊无几.对开发又没卵用,还不如来点干货看看咋用. 二.结构如下: impo ...
- React的使用与JSX的转换
前置技能:Chrome浏览器 一.拿糖:React的使用 React v0.14 RC 发布,主要更新项目: 两个包: React 和 React DOM DOM node refs 无状态的功能 ...
- Vue.js 2.0 和 React、Augular等其他框架的全方位对比
引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...
随机推荐
- .NETFramework:StaticValueInjecter
ylbtech-.NETFramework:StaticValueInjecter 1.程序集 Omu.ValueInjecter, Version=3.1.1.0, Culture=neutral, ...
- error:: undefined reference to symbol '__glewBufferSubData' 未定义的引用 以及 error: main.o: undefined reference to symbol 'glTexImage2D'
在把DSO移植到QT工程中,出现了 /usr/bin/ld: KeyFrameDisplay.o: undefined reference to symbol '__glewBufferSubData ...
- 1.8 Hive运行日志配置和查看
一.配置文件 1.重命名配置文件 # 把/opt/modules/hive-0.13.1/conf/hive-log4j.properties.template重命名为hive-log4j.prope ...
- c/c++面试19-22----inline的那些事儿
19 为什么引入内联函数 a:宏定义为什么效率高 通常替代c语言中表达式形式的宏定义来解决程序函数调用问题,使用的是预处理器实现,没有参数压栈等到做. 缺点: (1) 仅仅进行简单的替换,不能进行参数 ...
- Jmeter + Junit
在使用jmeter中Junit的功能之前,最好将接口以手动的方式调通,可以参考 Jmeter之HTTP Request 下面开始讲一下如何使用Junit功能 1. 编写测试类 JmeterJunit ...
- npm切换到淘宝镜像
1. npm简介 1.1.说明:npm(node package manager)nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等): 1.2.使用npm安装插件:命令提示符执 ...
- [Xcode 实际操作]七、文件与数据-(15)单例模式的使用
目录:[Swift]Xcode实际操作 本文将演示单例对象的使用. 在项目名称上点击鼠标右键,弹出右键菜单,选择[New File]新建文件命令, 在弹出的模板选项窗口中,选择[Swift]文件选项, ...
- 【OpenJ_Bailian - 3468】电池的寿命(贪心)
电池的寿命 Descriptions: 小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电.为了保证能够长时间玩游戏,他买了很多5号电池,这些电池的生产商不同,质量也有差异,因而使用寿命也有所不同 ...
- OSPF-1-OSPF的数据库交换(4)
4.DD交换:主/从关系 当两台路由器之间形成了邻居关系后(ExStart),邻居双方需要决定在数据库交换的过程中,哪台路由器的角色是主,哪台路由器的角色是从.主和从这两个角色决定了DD包交换过程 ...
- [题解](堆)luogu_P1631序列合并
思路来自题解 作者: Red_w1nE 更新时间: 2016-11-13 20:46 在Ta的博客查看 72 最近有点忙 没时间贴代码了== [分析] 首先,把A和B两个序列分别从小到大排序,变成两 ...