摘要:更加需要注意的東西是無法繼承帶來的性能問題??雌饋淼拇_是還不錯。表示不需要自動綁定的函數的名字。并且并沒有成為標準,但是其實也差不多了,并不擔心。結語這里的所有的解決思路都各有千秋吧。
文章來自我個人的Github
)
在平時的開發里面,總會碰到handle綁定的問題。如果你和我一樣懶或者思考過,你會覺得這個過程實在是太煩了吧。這里記錄一下我的思路和歷程。
這里以一個按鈕的點擊事件來做示例。
class App extends React.Components { state = { count: 0 } clickHandler () { const count = this.state.count + 1 this.setState({ count }) } render() { return ( ) } }
這個例子的目的是點擊按鈕觸發clickHandler來讓計數器加1。我們可以用兩種不同的方式來觸發這個handle,因為我們使用了this.setState,所以我們都必須要給函數綁定this。亦或是使用箭頭函數處理這個地方。
直接在jsx里面bind(this)嗯 這個的確可以。但是寫起來非常的長看起來也挺丑的。有個問題是每次重渲染的時候都會重新bind一次函數,對于比較大的列表來說這個地方非常不可取。
使用箭頭函數把clickHandler改成如下的范式。
clickHandler = () => { const count = this.state.count + 1 this.setState({ count }) } // render ...
誒這樣看起來會好很多誒。但是如果你有強迫癥你會發現一件事情。如果我們加上生命周期函數和一些其他的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如果你了解過ES7的decorator。你會發現上面的寫法完全可以使用decorator的形式表示,并且這個庫也支持在typescript上面使用。并且結構會非常的清晰。于是你找到了autobind-decorator這個庫。它能幫助到我們,給我們想要的東西,文檔一開始就告訴我們。
// Before: // After:
用之前...用之后的樣子,很好就是我們要的。 這個庫有個缺點就是必須的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,認為這是所有解決方案里面最好的一個了,但是要引入一個額外的依賴還是有點麻煩。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/109286.html
摘要:盡管已經受到高度贊揚,團隊仍然認為有必要構建和發布。用來描述組件的所有信息都將作為對象傳遞給。這是一個巨大的勝利,因為它更好地與標準保持一致。 showImg(https://segmentfault.com/img/bVbvYyy?w=880&h=369); 原文:https://dev.to/tylermcginnis/why-react-hooks-51lj.... 譯者:前端...
摘要:案例持續觸發事件時,并不立即執行函數,當毫秒內沒有觸發事件時,才會延時觸發一次函數。也以函數形式暴露普通插槽。這樣的場景組件用函數式組件是非常方便的。相關閱讀函數式組件自定義指令前言 有echarts使用經驗的同學可能遇到過這樣的場景,在window.onresize事件回調里觸發echartsBox.resize()方法來達到重繪的目的,resize事件是連續觸發的這意味著echarts...
摘要:檢查空值不要去檢查是否存在某個值,快使用。當你的值是對象或者數組時,使用聲明嵌套數據的預期類型。命名事件可以使用自定義事件替代預設的事件名。 原文:react-patterns 代碼結構 class definition constructor event handlers component lifecycle getters render defaultProps p...
閱讀 433·2019-08-29 12:44
閱讀 3011·2019-08-26 17:49
閱讀 2439·2019-08-26 13:40
閱讀 1187·2019-08-26 13:39
閱讀 3665·2019-08-26 11:59
閱讀 1828·2019-08-26 10:59
閱讀 2466·2019-08-23 18:33
閱讀 2698·2019-08-23 18:30