React Bind Handle的思索

文章来自我个人的
Github

)

在日常平凡的开辟内里,总会遇到handle绑定的题目。假如你和我一样懒或许思考过,你会以为这个进程实在是太烦了吧。这里纪录一下我的思绪和进程。

这里以一个按钮的点击事宜来做示例。

class App extends React.Components {
    state = {
        count: 0
    }

    clickHandler () {
        const count = this.state.count + 1
        this.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 + 1
    this.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 + 1
    this.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

假如你相识过ES7decorator。你会发明上面的写法完全能够运用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
  }

  @boundMethod
  method() {
    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}. Or
fetch.then(this.handleDone) — Dan Abramov‏

既能够在函数上,也能够在类上运用的@autobind

import autobind from 'autobind-decorator'

class Component {
  constructor(value) {
    this.value = value
  }

  @autobind
  method() {
    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,以为这是一切处理方案内里最好的一个了,然则要引入一个分外的依靠照样有点贫苦。

    原文作者:nbsaw
    原文地址: https://segmentfault.com/a/1190000018727461
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞