使用react的小夥伴日漸增多,react簡單的api讓人很是快速上手,但是有時候,稍不注意,做出的東西也許不是看上去那麼美好,其中就有一個,那就是在React ClassComponent中,究竟使用哪種繫結姿勢好一點。
在 @Monster000 的文章 React.js繫結this的5種方法, 詳細的介紹了react的常用繫結姿勢,感謝 @Monster000 的付出。關於文章中討論的全部方法,前三種我們們拋去不談,只聊聊第四種bind繫結與第五種箭頭繫結。
先從class說起
class ArrowComponent{
method = () => {
// more code
}
}
複製程式碼
這裡是一個class Component, 大部分人初看,沒問題啊,標準寫法。
標準寫法?標準嗎?
先來這看看 -> 傳送門: Class 的基本語法
看完後發現,全篇討論都是建立在class上定義方法,只有一個關於屬性的,還是私有屬性,而且現階段不支援,寫法是這樣的
class Component{
#name = ``
}
複製程式碼
那到底支援不支援正常的表示式屬性呢,試驗一下
嘖嘖,可見,上面說的標準寫法,現在不是標準的同志們,它是不支援的。
現在回到現實,為什麼我們專案中這樣寫不會報錯呢?
那是因為現在能用上這麼新的語法的,沒有人在幹擼code, 都從babel或者typescript過了一下,那為什麼他們不報錯呢,不多說,直接實踐:
熟悉js原型鏈的同學一看就明白了,這不是我們想要的,我們想要的是這樣的:
到此,class的一些問題告一段落現在我們,在回過頭看bind繫結與箭頭繫結
箭頭繫結
通過上面得知,class中的箭頭方法暫時不支援,但為了讓我們寫頭爽,各種編譯器默許了這種存在,只不過在編譯結果上做了一點改變,如果只是一般的屬性定義,也無所謂,但是用這種寫法去bind this,嘖嘖,分析一下
function ComponentA(){
this.method = () => {
// more code
}
}
function ComponentB(){
constructor(){
this.method = thid.method.bind(this)
}
}
// 提醒一下,prototype.method不要用 () => ,不然會將this繫結到當前context, 且,無法再次改變this指向,.bind也不行
ComponentB.prototype.method = function(){}
複製程式碼
兩種寫法,一眼就能看懂
A中,每次生成A的例項時, method都會重新定義一次,是每一次,EveryTime,且只用A有效
(假如說有一1w個這樣的元件?每一個react元件都是X的例項,一個頁面有多少元件?)
B中,method只會定義一次,所有例項可直接使用。只有在react元件中需要繫結
(只所以這樣,是facebook官方怕有的人對這裡this產生誤解,很早之前其實是不用bind這一步的)
有的同學會說,bind不是也會生成一個新的func嗎?
再說bind
函式是有大小的,同學們
function a(){
// 1 line code
}
function b(){
// 10w line code
}
const c = a.bind(null)
const d = b.bind(null)
複製程式碼
這裡,a 跟 b 是同樣的大小嗎? 不是。
但 c 跟 d 是一樣大小的。
不信,上 bind:
Function.prototype.bind = function(context){
var args = Array.prototype.slice(arguments, 1),
F = function(){},
self = this,
bound = function(){
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return self.apply((this instanceof F ? this : context), finalArgs);
};
F.prototype = self.prototype;
bound.prototype = new F();
retrun bound;
};
複製程式碼
不管你函式有多大,bind只走自己的邏輯,在執行的時候呼叫一下繫結的那個函式而已。
總結
全手寫,累了,簡單結論,React ClassComponen中,錯,不只是React ClassComponen, 而是在現階段 Es Class中,不要使用箭頭定義方法, 因為這種寫法跟 js原型鏈一點關係沒有,完全放棄了例項共享原型鏈的優勢。
玩的愉快.