React基礎(四):組件輸出,爲什麼要用 key

上一篇博客中,我們講過花括號 { },其實花括號 { } 不僅能輸出數據,也能直接輸出組件。

比如,我們一般寫組件都是這樣用的:

我們也可以把 Cmp1 這個組件,直接的放到一個變量裏面:

並且,花括號 { } 不僅可以輸出組件,還可以輸出組件數組。

其實也非常的簡單,首先我們要有一個數組,只不過它裏面存的不是普通數據,而是組件:

首先,這種寫法頁面能出來,並沒有問題。

但是控制檯上面會有個警告。它說:在你這個數組裏面的每一個子元素,必須得有一個 key 這個屬性。

其實這個就涉及到了虛擬 DOM,我們在前面也描述過虛擬 DOM。如果你沒接觸過虛擬 DOM,就會感覺好高深,好厲害的樣子。但如果你真正懂了,其實並不難,這裏我們就用一張圖來簡單的理解:

所謂的虛擬 DOM,其實它是相對於真實 DOM 而言的。比如下圖中,左邊是 React,右邊是真實的頁面。

現在 React 中裏面有一些數據,它裏面存的就是虛擬 DOM,之前的博客也說過,虛擬 DOM 其實就是個 json。

然後它有一個 div,下面有三個 span。所以對應的,頁面裏面也是一樣,因爲虛擬 DOM 和真實 DOM 是一 一對應的。

我們在 React 裏面去操作,其實操作的就是左邊的 json。

但是現在有一個問題,就是右邊頁面裏面的東西,不可能是永遠靜態的。

如果這個時候,我在左邊新插入了一個 span。那是不是右邊的真實 DOM 也得跟着變?

這個就是 React 裏面虛擬 DOM 和真實 DOM 同步的問題。那麼問題來了,就是同步的時候,不是你想象的那麼簡單。

 

我們先來看一個數組的例子:

比如我現在有一個數組: [12, 12, 5, 8 ]。刪了一個 12,變成了:[ 12, 5, 8 ]。

那你能告訴我刪的是哪個 12 嗎?

再比如 [ 12, 5, 8 ] 變成了 [ 12, 9, 3 ],那你能告訴我它是怎麼變過來的嗎?

可能有人覺得是把 5,8 刪完之後添加了 9,3。也有人覺得是把 5 改成 9,把 8 改成 3 了。也有可能是刪了再添,添了在刪等等各種各樣的說法,這個根本沒法說。

同樣的,虛擬 DOM 也有這個問題。所以說虛擬 DOM 在實踐當中有一個巨大的困難,就是需要跟蹤左邊的數據,以及右邊它所對應的那個 DOM 標籤。也就是左邊的數據刪了或者改了,右邊對應的標籤也要跟着刪或者改。

 

所以,在虛擬 DOM 變化的過程當中,我們需要跟蹤這個變化,然後需要同步的去調整真實的 DOM 節點。

那麼有一種方法:你的數據只要跟之前不一樣了,我就把所有的 DOM 節點全刪了,然後再全都重新創建一遍。

這種方法肯定沒問題,但是你覺得性能和效率如何?肯定是不行的。

那麼在這個時候,它就必須得去想辦法跟蹤到底是誰變了,而 React 就是通過這個 key 來作爲跟蹤的一個依據。

簡單的來說,key 是一個屬性,它就像我們每個人的身份證一樣,是獨一無二的。

可以看到,加了 key 之後,它就不會報錯了。

但是這裏會有一個問題,你可能覺得奇怪:如果我這裏不用數組,而是用三個變量會怎麼樣呢?

這個操作和上面的數組是差不多的,但是我沒加 key,那爲什麼不報錯呢?

爲什麼只有成組添加的時候需要用 key,而不成組就沒有 key 的需求呢?

原因很簡單,因爲 React 其實可以自動的添加一個 key。

如果你用的是普通的單變量,一個一個的往裏面插,那麼你在插的過程當中,其實它就能跟蹤你的這個變量,你的變量是誰它是知道的,所以它就能夠準確的用這個 key 來表述出來。

但是如果成組的往裏面插就不一樣了。你這個數組,我是添了一個,還是刪了一個,就沒法說了,所以這個時候它就需要一個 key 的輔助。

所以用 key 需要注意三件事:

1,一個一個往裏插沒事,唯獨是插數組的時候,就需要 key。這一點我們是必須要知道的。

2,key 值絕對不能重複。

3,key 值一定不能變。因爲它本身就是依靠這個 key 來跟蹤你的變化,如果你的 key 瞎變,那它就認爲剛纔那個 key 消失了,那個標籤我就可以刪了,這又多出來一個,我還要再新創建一個。所以如果這個 key 亂變,輕則影響性能,重則整個頁面的 DOM 元素混亂。

 

然後我們繼續:

剛纔上面的寫法其實不太好,因爲我們很少會手動的去寫一個數組,都是循環出來的。

那循環的應該怎麼做呢,最先想到的肯定是 for 循環,那麼我們來看下:

這樣做是沒問題的,但是也不太好。因爲我們剛說過,key 是不能變的。

如果這個 arr 將來添加了一個東西:arr = [ 12, 11, 5, 8 ],就會導致 5 和 8 的 key 都變了。

所以說,用 index 作爲 key 是非常不好的。

那麼在開發中,這種 for 循環寫起來太麻煩了,如果撇開 key,有沒有簡單一點的循環寫法呢?

我們可以用 ES6 的 map。

可以看到,也能出來,並且沒有報錯。現在這種寫法就比 for 循環要簡單很多了。

其實我們還可以直接將 map 放到模板裏面:

我們在項目中其實就是這麼來寫的。

但是這樣寫只有一行,都擠在一起不太容易看,並且也不好換行。

這裏我個人有一個小習慣,就是在後面加一個括號 ( )

可以看到,這樣寫也是沒問題的。

這裏加的括號 ( ),其實和 return 裏面括號意思是一樣的。

這樣的話,它裏面的東西就可以隨便換行,寫起來,看起來也都方便一些。

所以,怎麼讓組件動態的加入進來,我們一般都是用 map 來做。

 

那麼我們已經瞭解了組件如何輸出,接下來我們就來看看組件如何去嵌套。

實際上來說,組件並沒有什麼特別的,它和 html 差不多,所以也可以和 html 一樣來嵌套。

所以組件是可以嵌套着用的,並且實際開發中,我們也就是這麼用的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章