React Bind Handle的思考
文章来自我个人的Github
在平时的开发里面,总会碰到handle
绑定的问题。如果你和我一样懒或者思考过,你会觉得这个过程实在是太烦了吧。这里记录一下我的思路和历程。
这里以一个按钮的点击事件来做示例。
class App extends React.Components {state = {count: 0}clickHandler () {const count = this.state.count + 1this.setState({ count })}render() {return (<button>Click me to show something in dev tools</button>)}
}
复制代码
这个例子的目的是点击按钮触发clickHandler
来让计数器加1
。我们可以用两种不同的方式来触发这个handle
,因为我们使用了this.setState
,所以我们都必须要给函数绑定this
。亦或是使用箭头函数
处理这个地方。
直接在jsx
里面bind(this)
<button onClick={this.clickHandler.bind(this)}>Click me to show something in dev tools
</button>
复制代码
嗯 这个的确可以。但是写起来非常的长看起来也挺丑的。有个问题是每次重渲染
的时候都会重新bind
一次函数,对于比较大的列表来说这个地方非常不可取。
使用箭头函数
把clickHandler
改成如下的范式。
clickHandler = () => {const count = this.state.count + 1this.setState({ count })
}// render ...
<button onClick={this.clickHandler)}>Click me to show something in dev tools
</button>
复制代码
诶这样看起来会好很多诶。但是如果你有强迫症你会发现一件事情。如果我们加上生命周期函数和一些其他的handler ... 比如这样。
componentDidMount () {}
componentWillMount () {}
componentWillUpdate () {}clickHandler = () => {const count = this.state.count + 1this.setState({ count })
}antoherHandle = () => {}
复制代码
你会发现这里生命周期函数和handler
的写法不一样。但是你的确可以让它们变得一样,比如把生命周期函数改成箭头函数。可是这看起来不会觉得很怪异吗。毕竟你一直以来都不是这么做的。
除此之外箭头函数无法被继承,这意味着如果你的子组件需要继承函数,这将会导致无法做到。更加需要注意的东西是无法继承带来的性能问题。这会导致每次创建组件都会创建新的方法导致额外的开销(因为箭头函数的实现其实是直接在constructor
函数里丢方法),如果是通过继承,那么它们这些方法总是来自同一个prototype
,js编译器是会做优化的。
详细文章可以看这一篇Arrow Functions in Class Properties Might Not Be As Great As We Think。
在构造器里面使用bind(this)
通过构造器来写绑定函数其实看起来是不错的
constructor (props) {super(props)this.clickHandler = this.clickHandler.bind(this)this.antoherHandle = this.antoherHandle.bind(this)
}
复制代码
既解决了性能(内存)的问题。还能做很多有意思的事情比如说,利用现有的方法添加更有语义化的方法。
constructor (props) {super(props)this.clickHandler = this.clickHandler.bind(this)this.antoherHandle = this.antoherHandle.bind(this)this.clickWithOne = this.clickHandler.bind(this, 1)
}
复制代码
这样就能产生每次都会传参数1
的新事件。看起来的确是还不错。但是仍然有问题。当你的方法线性的增加的时候,如果有三个四个五个六个的时候,你可能需要一个一个的绑定。添加它们到构造函数里面,更糟糕的可能是通过复制粘贴以前写的方法,你会绑定错误的函数。就像这样。
constructor (props) {super(props)this.clickHandler = this.clickHandler.bind(this)this.antoherHandle = this.antoherHandle.bind(this)this.clickWithOne = this.antoherHandle.bind(this, 1)
}
复制代码
你必须在运行的时候才知道你的clickWithOne
绑定的其实是antoherHandle
。如果你没测试过,那么很可能就会出现一些你难以理解的问题或者bug。
自动绑定
如果你动脑想想会发现可以写一个autobind
的方法来自绑定函数呀。但是你很懒没有去写,你通过github
搜索到了一个叫做React-autobind的库。看起来好像还不错。
constructor(props) {super(props);autoBind(this);
}
复制代码
甚至可以不绑定某些方法。
constructor(props) {super(props);autoBind(this, {wontBind: ['leaveAlone1', 'leaveAlone2']});
}
复制代码
或者指定只绑定某些方法。
constructor(props) {super(props);autoBind(this, {bindOnly: ['myMethod1', 'myMethod2']});
}
复制代码
看起来似乎是妙极了。但是你会发现这个写法其实还是很繁琐啊。要写一坨东西。。打开源码看一眼你会发现有一个默认的wonbind
列表。
let wontBind = ['constructor','render','componentWillMount','componentDidMount','componentWillReceiveProps','shouldComponentUpdate','componentWillUpdate','componentDidUpdate','componentWillUnmount'
];
复制代码
表示不需要自动绑定的函数的名字。但是这个列表非常的糟糕,因为随着React版本的提升,某些钩子和方法都会被废弃,随着时间可能还会增加增多的方法。
这个库也很久没更新了。差评还是放弃吧。。。
Autobind-decorator
如果你了解过ES7
的decorator
。你会发现上面的写法完全可以使用decorator
的形式表示,并且这个库也支持在typescript
上面使用。并且结构会非常的清晰。于是你找到了autobind-decorator这个库。它能帮助到我们,给我们想要的东西,文档一开始就告诉我们。
// Before:
<button onClick={ this.handleClick.bind(this) }></button>// After:
<button onClick={ this.handleClick }></button>
复制代码
用之前...用之后的样子,很好就是我们要的。 这个库有个缺点就是必须的IE11+以上的版本才支持,但是这其实也还好。
另外就是你的开启decorator
的支持在babel
的配置里面。
{"plugins": [["@babel/plugin-proposal-decorators", { "legacy": true }],]
}
复制代码
我们来看看推荐的用法。
import {boundMethod} from 'autobind-decorator'class Component {constructor(value) {this.value = value}@boundMethodmethod() {return this.value}
}let component = new Component(42)
let method = component.method // .bind(component) isn't needed!
method() // returns 42
复制代码
给方法绑定this,而不是整个类,这么做是更加合理的。因为不是每个方法都需要用到this
的。如Dan
所说。
It is unnecessary to do that to every function. This is just as bad as autobinding (on a class). You only need to bind functions that you pass around. e.g.
onClick={this.doSomething}
. Orfetch.then(this.handleDone)
-- Dan Abramov
既可以在函数上,也可以在类上使用的@autobind。
import autobind from 'autobind-decorator'class Component {constructor(value) {this.value = value}@autobindmethod() {return this.value}
}let component = new Component(42)
let method = component.method // .bind(component) isn't needed!
method() // returns 42// Also usable on the class to bind all methods
// Please see performance if you decide to autobind your class
@autobind
class Component { }
复制代码
只能作用于类的@boundClass,我们难免也会有全都需要绑定到this
的情况这时候我们直接boundClass
会更加的简洁。
import {boundClass} from 'autobind-decorator'@boundClass
class Component {constructor(value) {this.value = value}method() {return this.value}
}let component = new Component(42)
let method = component.method // .bind(component) isn't needed!
method() // returns 42
复制代码
缺点也是有的,并不能像constructor
那样自己随随便便的定不同的方法名通过原有的方法,必须的写出一个新的,但是这是小问题,无伤大雅。并且descorator
并没有成为标准,但是其实也差不多了,并不担心。
结语
这里的所有的解决思路都各有千秋吧。怎么取舍还是看自己,这里就不一一列出来各自的对比了 ,于我个人而言会偏好Autobind-decorator
,认为这是所有解决方案里面最好的一个了,但是要引入一个额外的依赖还是有点麻烦。
转载于:https://juejin.im/post/5ca07af9e51d4560dc4b65e0
React Bind Handle的思考相关推荐
- 基于React开发范式的思考:写在Lesx发布之际
例子:lesx-example webpack loader: lesx-loader 一些背景 现在前端框架已经呈现出React.Angular.Vue三足鼎立的局势,对于三者的对比以及技术选型的思 ...
- 用React的方式思考
2019独角兽企业重金招聘Python工程师标准>>> 构建大型.反应迅捷的web app,我首选react.我们在facebook和instagram中都用了它,扩展的不错. 当你 ...
- 了解React.js中数组子项的唯一键
本文翻译自:Understanding unique keys for array children in React.js I'm building a React component that a ...
- Flutter React编程范式实践
作者:闲鱼技术-匠修 Flutter Widget的设计灵感来源于React,是一款原生就立足于响应式的UI框架.本文基于Flutter特点,试图结合闲鱼在Flutter的工程应用来谈下我们对Flut ...
- React笔记---kalrry
React笔记---kalrry 前言 文档 一.react 1. 什么是react 2. 特点 3. react的发展史 4. cra---create-react-app 5. 拿到空项目怎么办? ...
- 从零开始的React学习(一)
React基础 写在前面:这是我学习B站黑马React视频前75p所作的笔记. 后续的学习也会整理出笔记,供自己之后翻阅,也希望能给你带来一些帮助. (1)概述 用于构建用户界面的JavaScri ...
- React DnD简明教程
React DnD简明教程 概述 React Dnd不同于其他的拖拽库,如果你以前没有用过它可能会被吓到.然而,一旦你了解了它设计的一些核心概念,它将变得有意义.我建议你在阅读文档其他部分之前,先阅读 ...
- react 最佳实践_最佳React教程
react 最佳实践 React is a JavaScript library for building user interfaces. It was voted the most loved i ...
- react 数据可视化_使用d3创建数据可视化并在2020年做出React
react 数据可视化 Data visualisation and application technologies have evolved greatly over the past decad ...
最新文章
- 科研赢家比其他人多了哪一个特点?
- 怎么计算一个对象占用的内存
- .Net Web项目安装包制作(三)补充说明
- 对Kalman Filter的理解
- 写给前端新手看的一些模块化知识
- python如果选择不在列表里_Python-list.remove(x)x不在列表中
- 如何判断微信内置浏览器(JS PHP)
- JS左侧竖向滑动菜单
- 名校大厂 AI 高手云集,芒果 TV 音视频算法大赛硕果累累
- 前端js如何生成一个对象,并转化为json字符串
- 如何把qq挂到云服务器,云服务器挂QQ软件常用方法和注意问题
- 腾讯云— LAMP 架构个人实践分享
- rtl驱动 ubuntu 禁用_ubuntu18.04系统中使用dkms安装wifi驱动rtl8723be的方法
- Markdown——图片、文字显示居中的一种方法
- 2020我也当了面试官-java面试题之一
- PO系列之 PO中使用webService
- SCAU高级语言程序设计OJ
- NOI2019滚粗记
- python打开摄像头_Python 调用摄像头
- SparkSQL之“Dataset和Dataframe