最近在項目中引入了React Native,在開發過程中遇到了不少問題。其中listView的刷新機制和子組件的刷新問題尤為頭痛,在此記錄一下。
一、ListView的刷新機制
在RN中加入一個ListView組件時,你需要指定ListView的datasource即數據來源。一般我們會在構造函數中設置ListView的datasource:
其中dataBlob是字典嵌套的數組類似于:{key1:[row1, row2, row3], key2: [row1, row2],...},sectionIdArr是所有key的數組[key1, key2,...]。若不需要section時dataBlob可以使用純數組[row1, row2, row3,...]。
而其中非常重要的兩個函數rowHasChanged(r1, r2)、sectionHeaderHasChanged(r1, r2)指定了什么時候調用renderRow()和renderSectionHeader()來刷新ListView。
rowHasChanged: (r1, r2)=> r1!==r2
意思是當rowdata發生改變時調用renderRow()。這樣你重新給state里的dataSource賦值時就會調用ListView的renderRow()了。
在這里你必須注意一點:不可以在原有的dataBlob上修改,如下操作是不會觸發renderRow()的:
推薦使用JSON.parse(JSON.stringify(dataMap))來返回一個新的dataBlob,這樣可以簡單有效的觸發renderRow()的:
二、子組件的刷新與state問題
1、刷新問題
與圖所示,若我們在ListView上加一個選擇按鈕,點擊會有選中效果。有兩種做法,一種直接加一個Image在row上面,并在rowdata里面加入一個select字段來記錄選中狀態,點擊時改變ListView的Datasource來刷新這個image。不過這樣會很麻煩,要改變datasource,要重新調用reder(),這樣改變一個按鈕狀態會重刷整個界面相當不合理。第二種做法就是新建一個組件在組件里做這些操作。下面就說一下第二種方法
我們新建一個組件叫Button.js:
并在父組件里調用Button組件:
這樣點擊的時候按鈕就會切換狀態,并調用父組件的selectAll返回。而且不需要再父組件里重刷界面。
2、state問題
如果現在有個新需求,在刷新界面是要保持選中狀態,要如何去做呢?我們要了解,當組件已經加載過后,父組件重新render()時,子組件是不會重新調用constructor的。不過這時他們觸發componentWillUpdate方法,我們只要在這里重新給Button的state賦值就可以了:
并且在刷新的時候給button的props將seletcted傳遞過去就可以了。
三、結語
學習新技術的過程中難免會遇到這樣那樣的坑和難題,不過只有這樣人才能成長和進步,本文記錄總結了本人在使用RN的過程中遇到的一些問題。希望能給別的有點小小的幫助,文章中如有錯誤或紕漏還望不吝賜教。