作者博客傳送門(mén)
React Native現(xiàn)在所謂如火如荼,所以作者也不例外,趕緊來(lái)湊湊熱鬧。寫(xiě)這篇文章正式12月份了,也算是實(shí)現(xiàn)今年的目標(biāo),熟練使用React Native。到現(xiàn)在一共寫(xiě)了2個(gè)項(xiàng)目了,已經(jīng)能夠熟練寫(xiě)RN項(xiàng)目,現(xiàn)在也算是實(shí)現(xiàn)了這個(gè)小目標(biāo)。
之前寫(xiě)過(guò)一篇文章也是一個(gè)項(xiàng)目總結(jié)React Native項(xiàng)目實(shí)踐總結(jié)。不過(guò)這個(gè)項(xiàng)目比較小,最多能夠讓你入門(mén)吧,所以就想找個(gè)大的項(xiàng)目練練手。有幸發(fā)現(xiàn)了一個(gè)GitHub Popular這個(gè)APP,所以也就根據(jù)視頻動(dòng)手實(shí)現(xiàn)一下。
效果
gif有點(diǎn)大,想看效果的可以點(diǎn)擊下邊鏈接
差異
首先原來(lái)的GitHub Popular這個(gè)APP有些技術(shù)比較老了,比如
Listview已經(jīng)被廢棄。作者采用了FlatList這個(gè)官方推薦的控件,相比Listview,FlatList性能比較高,具體想了解的可以去官網(wǎng)查看在趨勢(shì)模塊導(dǎo)航中下拉框效果原作者使用了'Popover'這個(gè)第三方控件,但是由于
react-native-navigation,必須要把視圖加到window下,才能在導(dǎo)航欄上邊顯示,所以作者通過(guò)js與原生的交互封裝了一個(gè)原生控件來(lái)實(shí)現(xiàn)該效果。
BE52EE5B-9F2E-4167-B299-A7D853A5DED2.png
- APP的整體框架作者也沒(méi)采用原來(lái)的,雖然原來(lái)的靈活性各方面也比較好吧。這里使用了一個(gè)官方推薦的
react-native-navigation作為APP的整體框架,不過(guò)這里在切換主題的時(shí)候有一個(gè)坑(下邊將詳細(xì)介紹一下),如果不改原來(lái)代碼是實(shí)現(xiàn)不了的,其他用起來(lái)還是比較順手。
項(xiàng)目介紹
環(huán)境
開(kāi)發(fā)語(yǔ)言
- ES6
- React Native 0.50.4
用到的第三方
react-native-check-boxreact-native-htmlviewreact-native-navigationreact-native-parallax-scroll-viewreact-native-scrollable-tab-viewreact-native-sortable-listview
App 結(jié)構(gòu)
如果看作者源碼的話可能會(huì)一頭霧水,所以作者畫(huà)了兩個(gè)思維導(dǎo)圖,能夠讓大家最快的了解這個(gè)項(xiàng)目
項(xiàng)目結(jié)構(gòu)圖

數(shù)據(jù)流向圖

遇到的坑
雖然是按照視頻來(lái)寫(xiě),但是由于項(xiàng)目的結(jié)構(gòu)等一些差別還會(huì)導(dǎo)致一些坑
- 數(shù)據(jù)改變后通知刷新視圖,視圖未刷新
在收藏子模塊中,如果取消收藏了。我們則要在相應(yīng)的最熱、趨勢(shì)模塊也做相應(yīng)的視圖刷新,經(jīng)過(guò)調(diào)試之后發(fā)現(xiàn)不會(huì)刷新,經(jīng)過(guò)不斷調(diào)試發(fā)現(xiàn)是由于異步調(diào)用造成的,采用延遲通知即可
this.timer = setTimeout(()=>{
//一定要適當(dāng)?shù)难舆t一下,因?yàn)锳syncStorage可能還沒(méi)完全移除掉相應(yīng)的key。
DeviceEventEmitter.emit('ACTION_HOME',ACTION_HOME.A_UPDATE_FAVORITE);
},500)
<font color='red'>這里的timer一定要在componentWillUnmount()方法進(jìn)行釋放</font>
componentWillUnmount(){
this.timer&&clearTimeout(this.timer);
}
- 切換主題底部tabbar字體和圖片的顏色不能改變
由于作者使用react-native-navigation這個(gè)第三方控件。其實(shí)本質(zhì)就是封裝了原生控件,當(dāng)APP初始化之后,字體的顏色是該表不了了,不過(guò)圖片能夠改變。作者看了一下它的源碼,其實(shí)實(shí)現(xiàn)也不難,只要改一下原生封裝的代碼,對(duì)外提供一個(gè)方法就好。
- 自定義視圖的時(shí)候刷新要在主線程
在實(shí)現(xiàn)趨勢(shì)的下拉框過(guò)程中,點(diǎn)擊回調(diào)顯示下拉框的時(shí)候,要在主線程調(diào)用。
dispatch_async(dispatch_get_main_queue(), ^{
[KxMenu showMenuInView:[UIApplication sharedApplication].keyWindow
fromRect:CGRectMake([dic[@"ox"] floatValue], [dic[@"oy"] floatValue]+20, [dic[@"width"] floatValue], [dic[@"height"] floatValue])
menuItems:arrays];
});
- Can only update a mounted or mounting component...
Warning:
setState(...): Can only update a mounted or mounting component.
This usually means you called setState() on an unmounted component.
This is a no-op.
Please check the code for the xxx component.
這個(gè)問(wèn)題也是在趨勢(shì)模塊導(dǎo)航欄自定義標(biāo)題視圖中遇到的一個(gè)警告。場(chǎng)景就是導(dǎo)航欄標(biāo)題視圖點(diǎn)擊選擇[今天,本周,本月],選完之后要更新導(dǎo)航欄顯示的文字為用戶所選的。這里作者自定義了一個(gè)CustomTopBar.js,然后注冊(cè)了一個(gè)通知來(lái)監(jiān)聽(tīng)更新state來(lái)刷新頂部文字的顯示
componentDidMount(){
this.listner = DeviceEventEmitter.addListener(ACTION_CUSTOMTOPBAR.CHANGE_TITLE,(title)=>{
this.setState({
title:title
})
})
}
查來(lái)查去作者想這個(gè)component應(yīng)該沒(méi)有被unmount,要不怎么會(huì)顯示出來(lái)呢,而且標(biāo)題也會(huì)正常更新,這里只是一個(gè)警告。作者就反復(fù)看代碼,發(fā)現(xiàn)了一個(gè)問(wèn)題就是作者的listner沒(méi)有被釋放,所以就加入了釋放代碼,居然神奇般的警告就消失了
componentWillUnmount(){
if (this.listner) {
this.listner.remove();
}
}
感悟
第一個(gè)項(xiàng)目寫(xiě)的時(shí)候比較生疏,寫(xiě)第二個(gè)的時(shí)候就有點(diǎn)孰能生巧的感覺(jué),所以寫(xiě)的會(huì)比較快??匆曨l的時(shí)候最好別按部就班的去寫(xiě),最好一邊看然后暫停一下,自己去實(shí)現(xiàn)一下或者嘗試不同的實(shí)現(xiàn)方式去寫(xiě)。有時(shí)候看視頻其實(shí)也會(huì)忽略一些細(xì)節(jié),導(dǎo)致項(xiàng)目報(bào)錯(cuò),這時(shí)候不要慌,我們要充分利用debug模式配合Chrome來(lái)斷點(diǎn)遠(yuǎn)程調(diào)試,一點(diǎn)一點(diǎn)的運(yùn)行最終肯定會(huì)找到問(wèn)題所在。
