前言
React Native是一個跨平臺的使用JavaScript編寫最終生成移動端原生控件應(yīng)用的開源框架。React-Native也是比較成熟的跨平臺編寫移動應(yīng)用的解決方案。經(jīng)過幾年的發(fā)展膘茎,在該框架上涌現(xiàn)出了很多優(yōu)秀的庫披坏,基于這些庫我們可以更快的編寫出一個功能豐富的應(yīng)用伞梯。React-Native提供給了我們將原生模塊和原生UI組件封裝的方法谜诫,讓我們可以隨心拓展自己需要的原生功能喻旷,這極大豐富我們應(yīng)用的功能且预,也為使用React-Native編寫的應(yīng)用提供無限的可能。
RN中實現(xiàn)自定義下/上拉刷新的困境
在app中涮拗,下拉刷新和上拉加載更多是一個很常見的功能多搀。RN自然也提供了這樣的控件——RefreshControl來實現(xiàn)ScrollView的下拉刷新康铭。在列表組件FlatList、SectionList中直接提供onRefresh/refreshing這樣的屬性來實現(xiàn)下拉刷新夷野,通過onEndReached來實現(xiàn)上拉加載更多悯搔。是的妒貌,一切看起來都很完整菊碟。只是如果我們想要實現(xiàn)豐富的逆害、可高度自定義的下拉刷新和上拉加載更多時魄幕,RN提供給我們的就顯得捉襟見肘了梅垄。
RN提供的下拉刷新組件中只有一個類似菊花的指示圓圈,以及圓圈底部的文本机久。在樣式上膘盖,提供了修改菊花的顏色和大小侠畔,文字的內(nèi)容和顏色的屬性。菊花樣式如下圖所示:
很簡潔,是蘋果性冷淡的風(fēng)格瘦棋。
只是赌朋,在國內(nèi)的絕大多數(shù)app都不會使用只有一個菊花的刷新頭部樣式服球。從國內(nèi)的大廠的app來看,是豐富多彩的伐庭。面對這樣的需求,RN提供給我們的就無法滿足了集乔。
如果我們想要在WebView中實現(xiàn)下拉刷新的功能呢?很遺憾汗唱,RN沒有在WebView組件中提供可下拉刷新的屬性。不過我們可以根據(jù)RN提供的現(xiàn)有組件組合起來——即在ScrollView中套上WebView的方法來讓W(xué)ebView具備下拉刷新功能际插。只是這樣的缺陷同樣明顯,因為ScrollView和WebView都是可滑動組件,這就會導(dǎo)致有些時候力奋,我們拖拽的是網(wǎng)頁內(nèi)容景殷,因此不會有下拉刷新的效果咐旧。這個問題也是RN無法解決的。
如果我們想要在RN上實現(xiàn)自定義的刷新頭部和尾部樣式伊约,那也只能通過封裝原生模塊的的方式來達到目的了。是的,我們確實做到了霍殴。
iOS中的MJRefresh庫
如果你是iOS原生的開發(fā)者,那么你一定有聽過甚至使用過這個庫巾腕。MJRefresh是國人寫的在國內(nèi)使用得最廣泛的提供下拉刷新和上拉加載更多的庫之一。該庫提供了高度自定義header和footer的樣式和刷新過程的多種狀態(tài)。同時它使用簡單冀泻,一行代碼即可實現(xiàn)刷新效果溯祸。
將MJRefresh拓展到React-Native
我們知道博杖,RN提供給我們的刷新組件并不能很好的實現(xiàn)更多的自定義樣式。那么我們只能通過封裝原生模塊來實現(xiàn)自定義的header和footer了。
MJRefresh是通過KVO以及iOS運行時方法為原有的iOS控件新增下拉刷新屬性和方法莺匠。借鑒這一思路,與一般的組件封裝思路(通過繼承ScrollView原生的類來將MJRefresh封裝實現(xiàn)下拉刷新和上拉加載更多)不同卫袒,我們也可以通過運行時方式來為RN提供的可滑動組件(比如:ScrollView、FlatList转砖、SectionList、WebView)提供新的屬性和方法來實現(xiàn)對MJRefresh的封裝和使用鲸伴。
react-native-mjrefresh-ios
通過以上的思路府蔗,我們最終完成了這一任務(wù),并且在實際項目中得到檢驗和完善汞窗。最終封裝成一個庫:react-native-mjrefresh-ios
以下是示例效果圖之一:
安裝
集成方法非常的簡單姓赤,只需要將react-native-mjrefresh-ios下載下來,并將相應(yīng)文件夾拖入到ios項目中即可完成集成杉辙。詳細(xì)安裝方法請看這里
用法
集成完成之后模捂,RN的ScrollView捶朵、FlatList、SectionList狂男、WebView組件就多出了相應(yīng)的屬性和回調(diào)方法來實現(xiàn)下拉刷新和上拉加載更多综看。
為了使開發(fā)者容易上手使用,react-native-mjrefresh-ios的使用方法與RN提供的組件RefreshControl的用法一致岖食。
例如红碑,列表組件FlatList,可以通過如下新增屬性實現(xiàn)下拉刷新:
<FlatList
// 是否開啟下拉刷新
enableMJRefresh={true}
// 指定刷新狀態(tài)
mjRefreshing={this.state.refreshing}
// 拖拽刷新時泡垃,觸發(fā)的回調(diào)
onMJRefresh={this.loadDataList}
// 設(shè)置header樣式
mjHeaderStyle={{
// 指定屬性
}}
/>
在WebView中析珊,我們通過一行代碼即可實現(xiàn)下拉刷新:
<WebView
source={{uri: 'https://www.baidu.com'}}
nativeConfig={{
props:{
// 是否開啟下拉刷新
enableMJRefresh: true,
// 指定刷新狀態(tài)
// mjRefreshing: this.state.refreshing,
// 拖拽刷新時,觸發(fā)的回調(diào)
// onMJRefresh: this.reloadData,
// 設(shè)置header樣式
// mjHeaderStyle: {
// // 指定屬性
// }
}
}}
/>
但我們更推薦使用社區(qū)推薦的react-native-webview的WebView來加載網(wǎng)頁蔑穴,其下拉刷新功能我們也做了封裝:
import { WebView } from 'react-native-webview';
// ....
<WebView
source={{uri: 'https://www.baidu.com'}}
// 是否開啟下拉刷新
enableMJRefresh: true,
// 指定刷新狀態(tài)
// mjRefreshing: this.state.refreshing,
// 下拉刷新觸發(fā)時忠寻,的回調(diào)
// onMJRefresh: this.loadData,
// mjHeaderStyle: {
// // 指定樣式屬性
// }
/>
對于上拉加載更多,我們也提供了相應(yīng)的屬性和回調(diào)方法:
例如:
<FlatList
// 是否開啟上拉加載更多
enableMJLoadMore={this.state.enableLoadMore}
// 是否正在加載更多
mjLoadingMore={this.state.loadingMore}
// 是否已經(jīng)加載全部
mjLoadAll={this.state.isLoadAll}
// 觸發(fā)加載更多的回調(diào)
onMJLoadMore={this.loadMoreData}
// footer的樣式
mjFooterStyle={{
// 設(shè)置屬性
}}
/>
自定義header和footer樣式
react-native-mjrefresh-ios庫提供了非常多的屬性來自定義刷新組件的樣式存和。通過指定mjHeaderStyle和mjFooterStyle即可實現(xiàn)奕剃,具體可用的屬性可以查看這里
寫在最后
React-Native是被開發(fā)者廣泛使用的用于編寫跨平臺移動端應(yīng)用的框架之一。它盡管目前仍存在些不完善的地方捐腿,但它也仍然在不斷地迭代中纵朋。同時社區(qū)開發(fā)者也不斷貢獻自己的庫,使這個生態(tài)越來越完善和健壯茄袖。
react-native-mjrefresh-ios彌補了RN在iOS端無法自定義上/下拉刷新的缺陷操软,也提供了新的上/下拉刷新的方法。當(dāng)然react-native-mjrefresh-ios也存在著他的不足宪祥。RN作為跨平臺的解決方案聂薪,目前這個庫只提供了iOS端的解決方案,并沒有提供安卓端的解決方案品山。