根據(jù)我的項(xiàng)目需要,其實(shí)我需要一個(gè)很簡單的APP應(yīng)用又跛,但就是這樣一個(gè)簡單的APP應(yīng)用,我卻耗費(fèi)了大量時(shí)間和精力礼烈,因?yàn)椋訉?shí)在太多了,我就把我遇到的坑寫出來做個(gè)記錄数冬。
二、APP開發(fā)
我項(xiàng)目需要以下的頁面
一、主界面
二、登錄
三、個(gè)人中心
四、list
五、detail
由于APP與web不一樣,所以沒有URL的概念,相對(duì)應(yīng)的是導(dǎo)航器,初入RN,也沒有使用原生的navigator組件查牌,而是經(jīng)大神推薦查看了ant-design的組件Demo僧免,依葫蘆畫瓢使用了 navigation組件金踪。
1)Navigation組件
首先我們需要安裝 react-native-navigation
npm i -g react-navigation --save
注意枷餐,在ios下,所有安裝的npm包润匙,都要yarn一下诗眨,主要是依賴的問題,否則會(huì)提示 安裝成功孕讳,但依賴失敗錯(cuò)誤
命令:
yarn add react-native-navigation
安裝后匠楚,我們就可以使用了
navigation有很豐富的功能,具體可以到?https://reactnavigation.org/docs/navigators/?查看文檔
而我項(xiàng)目只需要使用到?StackNavigator 而沒有TabNavigator/DrawerNavigator導(dǎo)航厂财,所以我只介紹?StackNavigator 和導(dǎo)航切換的方法
引入navigation組件
import { StackNavigator,TabNavigator,NavigationActions } from 'react-navigation';
配置導(dǎo)航
import Login from './Login' // 其他場(chǎng)景
const FirstApp = StackNavigator({?
?????????????????IndexScreen: {?
?????????????????????????screen: IndexScreen, // initialRouteName: 'IndexScreen' navigationOptions:({ navigation })=>({
????????????????????????????????????//headerTitle: '導(dǎo)航標(biāo)題',headerLeft: () 可以設(shè)置 headerTitle headerLeft headerRight等芋簿,具體參考官方文檔
? ? ? ? ? ? ? ? ? ? ? ? ?})
? ? ? ? ? ? ? ? },
????????????????// 其他場(chǎng)景: {screen: 場(chǎng)景名稱},
????????????????Login:{screen: Login},
? ? ? ? ? ? ? ? ......
? ? ? ? },
????????{
? ? ? ? ? ? ? ? // ....這里是其他公共配置
? ? ? ? ? ? ? ? // 例如?initialRouteName?navigationOptions等,具體參考官方文檔或網(wǎng)上的navigation的配置資料
????????});
在Component中也可配置navigationOptions
static navigationOptions = ({navigation, screenProps}) => ({
????????headerTitle: '導(dǎo)航標(biāo)題'
});
請(qǐng)注意璃饱,navigationOptions的配置優(yōu)先級(jí)為:
StackNavigator中的navigationOptions <?Component中的navigationOptions <?StackNavigator中的Screen的配置
會(huì)按優(yōu)先級(jí)進(jìn)行覆蓋
然后是將組件加入APP的component
在registerComponent的component中
render() {?
?????????????return (
????????????????<FirstApp style={{backgroundColor:'#ffffff'}} ref={nav => { this.navigator = nav; }} />
????????????)
}
至此与斤,navigation就配置完成,那么對(duì)應(yīng)的支持的方法分為幾種
第一種帜平,是常用的在子組件中調(diào)用
可以通過
this.props.navigation.navigate('Screen Name',{...params});?
進(jìn)行跳轉(zhuǎn)或
this.props.navigation.goBack();
進(jìn)行返回
第二種靠瞎,在StackNavigator中的navigationOptions中使用
navigationOptions: ({navigation})=>({
? ? ? ? //...在headerLeft等組件的onPress方法中 ()=>{
? ? ? ? //? ? ? navigation.goBack();
? ? ? ? // 或
? ? ? ? //? ? ??navigation.navigate('Screen Name',{...params});
? ? ? ? // }
? ? ? ? // 請(qǐng)注意厨疙,在這里需要用到 TouchableOpacity 組件包括按鈕,touchablehighlight會(huì)報(bào)錯(cuò),請(qǐng)注意
});
還有一個(gè)特別值得注意的是溯饵,當(dāng)你只有headerRight時(shí),需要設(shè)定headerLeft為一個(gè)空的view佑刷,否則治唤,會(huì)導(dǎo)致標(biāo)題無法居中
headerLeft: (
? ? ? ? <View style={{height: 44,width: 55,paddingRight:15} }/>
)
第三種箍邮,在registerComponent 中調(diào)用導(dǎo)航方法,這里主要是我使用了極光PUSH所以會(huì)在監(jiān)聽時(shí)調(diào)用導(dǎo)航器叨叙,通過控制臺(tái)打印this對(duì)象發(fā)現(xiàn)了這個(gè)方法
this.navigator._navigation.navigate('Screen Name',{...params});
或
this.navigator._navigation.goBack();
至此锭弊,Navigation教程完成,相信你能配置一個(gè)符合你的導(dǎo)航器
2) 登錄權(quán)限驗(yàn)證
然后就是User登錄判斷擂错,我的需求是需要用戶登錄味滞,那我APP就需要判斷,而又不應(yīng)該使用cookie來進(jìn)行處理钮呀,查閱了資料后剑鞍,發(fā)現(xiàn)用戶登錄狀態(tài)判斷代碼,但有錯(cuò)誤爽醋,會(huì)導(dǎo)致bundle報(bào)錯(cuò)蚁署,所以我對(duì)此進(jìn)行了修正
首先我們需要一個(gè)本地儲(chǔ)存引擎,我這里使用的是react-native-storage
用上面的npm方法進(jìn)行安裝
npm i -g react-native-storage --save
yarn add?react-native-storage
資料上說官方并不推薦直接使用storage蚂四,所以我按教程封裝了一個(gè)storage方法放在storageUtil.js
var storage = new Storage({
????// 最大容量光戈,默認(rèn)值1000條數(shù)據(jù)循環(huán)存儲(chǔ)
????size: 1000,
????// 存儲(chǔ)引擎:對(duì)于RN使用AsyncStorage,對(duì)于web使用window.localStorage
????// 如果不指定則數(shù)據(jù)只會(huì)保存在內(nèi)存中遂赠,重啟后即丟失
????storageBackend: AsyncStorage,
????// 數(shù)據(jù)過期時(shí)間久妆,默認(rèn)一整天(1000 * 3600 * 24 毫秒),設(shè)為null則永不過期
????defaultExpires: null,
????// 讀寫時(shí)在內(nèi)存中緩存數(shù)據(jù)解愤。默認(rèn)啟用镇饺。
????enableCache: true,
// 如果storage中沒有相應(yīng)數(shù)據(jù),或數(shù)據(jù)已過期送讲,
// 則會(huì)調(diào)用相應(yīng)的sync方法奸笤,無縫返回最新數(shù)據(jù)。
// sync方法的具體說明會(huì)在后文提到
// 你可以在構(gòu)造函數(shù)這里就寫好sync的方法
// 或是寫到另一個(gè)文件里哼鬓,這里require引入
// 或是在任何時(shí)候监右,直接對(duì)storage.sync進(jìn)行賦值修改
//sync: require('./sync')? // 這個(gè)sync文件是要你自己寫的
})
// 然后設(shè)置全局對(duì)象,由于我是APP所以不存在web 輕應(yīng)用异希,所以不需要用window.storage = storage;而是global.storage = storage;
global.storage = storage;
設(shè)置好后健盒,我需要一個(gè)Global.js來判斷當(dāng)用戶打開APP時(shí)是否登錄
//用戶登錄數(shù)據(jù)
global.user = {
????loginState:'',//登錄狀態(tài)
????userData:'',//用戶數(shù)據(jù)
};
//刷新的時(shí)候重新獲得用戶數(shù)據(jù)
storage.load({
????key: 'loginState',
}).then(ret => {
????global.user.loginState = true;
????global.user.userData = ret;
}).catch(err => {
????global.user.loginState = false;
????global.user.userData = '';
})
然后在registerComponent中import這兩個(gè)包,就完成了用戶的驗(yàn)證
注意:但實(shí)際情況卻是称簿,storage.load安卓下并未觸發(fā)扣癣,我并不清楚這是什么情況引起的,但I(xiàn)OS下又觸發(fā)了憨降,并且調(diào)試并未出現(xiàn)錯(cuò)誤父虑,所以我大膽猜測(cè)是import的時(shí)候,并未初始化完成storage授药,導(dǎo)致load方法并未實(shí)際執(zhí)行士嚎,可能這涉及到RN本身的機(jī)制呜魄,所以我又想了一個(gè)辦法,我封裝了一個(gè)SUser.js的全局方法莱衩,在每個(gè)組件的componentWillMount中進(jìn)行驗(yàn)證爵嗅,當(dāng)global.user.loginState==false時(shí)我就執(zhí)行清除用戶數(shù)據(jù)并返回登錄界面
import JPushModule from 'jpush-react-native';
var Suser = {
????phone:null,
????checklogin:function(t){
????if (!global.user.loginState) {
????????storage.load({
????????????key: 'loginState'
????????}).then(ret => {
????????????global.user.loginState = true;
????????????global.user.userData = ret;
????????????global.user.phone = ret.phone;
????????}).catch(err => {
????????????JPushModule.clearAllNotifications();
????????????global.user.loginState = false;
????????????global.user.userData = '';
????????????t.navigate('Login');
????????})
????}
},
logout:function(t){
????storage.remove({
????????key: 'loginState'
????});
????global.user.loginState = false;
????global.user.userData = '';
????JPushModule.clearAllNotifications();
????t.navigate('Login');
}
}
global.Suser = Suser;
這樣,就解決了用戶登錄判斷笨蚁,雖然方法很笨睹晒,但有效,如有大神有更好的方法括细,請(qǐng)聯(lián)系我册招,感激不盡!@占!
還有注意:當(dāng)你在chorme中查看console時(shí)虑鼎,發(fā)現(xiàn)app init了2次或更多辱匿,導(dǎo)致所有事件都會(huì)執(zhí)行兩次,例如alert炫彩,那么只是模擬器問題匾七,關(guān)閉APP,重新啟動(dòng)就好了江兢,原因我不清楚昨忆,偶爾會(huì)出現(xiàn)重復(fù)2次或3次或4次,調(diào)試了很久也沒解決杉允,正式包不存在這個(gè)問題邑贴,問了大神也不清楚,代碼并未有問題叔磷。