激动不已 ~
自从 [email protected] 版本之后,进入了内网编程。在一个封闭的小圈圈里,以 [email protected] 版本进行编程。全靠徒手手撸 代码 ,总觉得大能量无处尽放 !
今天决定使用疫情期间学习的Typescript语言,来实现一个 [email protected] 版本的移动APP。
项目使用Typescript语言,集成了路由 导航react-navigation 和 react-native-material-tabs。分别实现了 登录页、库存列表页和库存单品详情页 3个页面。
先附带一下自己用Photoshop绘制的效果图***
接下来,配置具备Typescript语言编程环境的 [email protected] 的项目。
介绍一个具备ts语言的RN模板,指令即可完成项目初始化
新建一个目录,在dos窗口执行终端命令 npx react-native init CarglassApp --template react-native-template-typescript
执行过程中,你或许会遇到这个 error error An unexpected error occurred: "https://registry.npm.taobao.org/react-native-template-react-native-template-typescript: Not found".
不捉急,有解决方案:
remove legacy react-native-cli
npm uninstall -g react-native-cli
install new thing
npm i -g @react-native-community/cli
and you can new project with react-native-template-typescript
npx react-native init MyApp --template react-native-template-typescript
然后你会发现,it works .
而报错原因是因为我在 react-native 官网搭建环境里配置所导致的资源路径不对。通过以上 的修改则it works .
# 使用nrm工具切换淘宝源
npx nrm use taobao
# 如果之后需要切换回官方源可使用
npx nrm use npm
CarglassAPP 项目初始化成功之后,让工程在安卓模拟器中跑起来。执行命令 cd CarglassApp && yarn react-native run-android
初始化工程
yarn react-native run-android
运行成功
效果展示
至此具备 Typescript 语言配置的 react-native 工程就配置完成了。
由于 RN 高版本的更新导致,安卓模拟器设备无法通过快捷键弹出调试菜单。但是可以在终端使用指令弹出调试菜单 adb shell input keyevent 82
经过一天的编码,展示一下成果图:
在该Demo项目中,使用到了Typescript语言下配置的路由导航react-navigation。
程序编写过程中在路由导航时,遇到了很多问题。在Typescript的路由配置难度上要高于Javascript。回顾一下解决该问题的过程,在Google上搜到了一篇文章并结合react-avigation官网。对于编写完好的程序,在
import {createAppContainer , createStackNavigator} from "react-navigation";
的lib属性 createStackNavigator上代码检查报错。
然后强制执行yarn react-native run-andorid
命令之后,看到报错具体内容
紧接着根据提示安装引用库,yarn add react-navigation-stack
之后又有很多报错,缺少这个库缺少那个库,react-native 命令不存在等等!
最终解决方案就是 提示缺少什么就装什么
大概需要安装的lib有(如有不足请继续安装):yarn add react-native react-native-gesture-handler react-native-safe-area-context react-native-screens react-navigation react-navigation-stack
还有部分对应的类型声明(如有不足请继续安装): yarn add @react-native-community/masked-view @react-navigation/native @react-navigation/stack @types/react @types/react-navigation
源码附赠展示,点击下载查看
package.json 的配置文件上的版本内容
react-native | react-navigation | @types/react-navigation | typescript | 省略… |
---|---|---|---|---|
^0.61.5 | ^4.2.2 | ^3.4.0 | 3.7.3 | 省略… |
成功运行之后的效果源码:
//APPEntrance.tsx
import React from 'react';
import {
AppRegistry,
Text,
TouchableOpacity
} from 'react-native';
import AppContainer from './src/screens/AppContainer';
export default class HomeScreen extends React.Component {
render() {
return <AppContainer />
}
}
//APPContainer.tsx
import React, { Component } from 'react';
import {
SafeAreaView,
StyleSheet,
View,
Text,
StatusBar,
Image,
Dimensions,
ImageSourcePropType,
ScaledSize,
FlatList,
TextInput
} from 'react-native';
import RespoList from './RespoList';
import {createAppContainer } from "react-navigation";
import { createStackNavigator, NavigationStackScreenProps } from 'react-navigation-stack';
import { TouchableOpacity } from 'react-native-gesture-handler';
import DeviceConfs from '../confs/DeviceConfs';
import ImgConfs from '../../src/confs/ImgConfs';
type AppProps = NavigationStackScreenProps;
class AppContainer extends React.Component<AppProps> {
static navigationOptions = {
title: '',
};
render(): React.ReactNode {
return (<View style={{backgroundColor: '#418dfb', flex: 1, alignItems: 'center'}}>
<Image source={ImgConfs.icon_logo_word} resizeMode={'contain'}
style={{width: 120, height: 80, marginTop: 80}}/>
<TextInput
style={{ height: 42, borderColor: '#6a6a6a', borderWidth: 1, borderRadius:4, marginTop:50,
backgroundColor:'white', width: DeviceConfs.sWidth * 0.75 , paddingHorizontal: 12}}
placeholder={'用户名/手机号'} placeholderTextColor={'rgba(146,146,146,0.6)'}/>
<TextInput
style={{ height: 42, borderColor: '#6a6a6a', borderWidth: 1, borderRadius:4, marginTop:20,
backgroundColor:'white', width: DeviceConfs.sWidth * 0.75 , paddingHorizontal: 12}}
placeholder={'密码'} placeholderTextColor={'rgba(146,146,146,0.6)'}/>
<TouchableOpacity activeOpacity = {0.8}
style={{borderColor:'white', borderWidth:1, backgroundColor:'white', borderRadius: 6,marginTop: 100,
width:DeviceConfs.sWidth * 0.75, height:42, justifyContent: 'center', alignItems:'center'}}
onPress={()=>{this.props.navigation.navigate('RespoList')}}>
<Text style={{color:'#418dfb', fontSize: 16, fontWeight:'bold'}}>{'立即登录'}</Text>
</TouchableOpacity>
<Image source={ImgConfs.bg_logo1} resizeMode={'contain'}
style={{width: 120, height: 80, position:'absolute', top: DeviceConfs.sHeight * 0.35, left: 15}}/>
<Image source={ImgConfs.bg_logo2} resizeMode={'contain'}
style={{width: 120, height: 80, position:'absolute', top: DeviceConfs.sHeight * 0.28, left: DeviceConfs.sWidth * 0.6}}/>
<Image source={ImgConfs.bg_logo3} resizeMode={'contain'}
style={{width: 120, height: 80, position:'absolute', top: DeviceConfs.sHeight * 0.75, left: DeviceConfs.sWidth * 0.4}}/>
</View> );
}
}
const AppNavigator = createStackNavigator({
AppContainer: { screen: AppContainer },
RespoList: { screen: RespoList }
}, {
defaultNavigationOptions:{
header: null
}
});
export default createAppContainer(AppNavigator);
//RespoList.tsx
import React, { Component } from 'react';
import {
SafeAreaView,
StyleSheet,
View,
Text,
StatusBar,
Image,
Dimensions,
ImageSourcePropType,
ScaledSize,
FlatList,
ScrollView
} from 'react-native';
import {ResItem} from '../interfaces/Types-list';
import RespertoryItem from '../components/RespertoryItem';
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
import DeviceConfs from '../confs/DeviceConfs';
import ImgConfs from '../confs/ImgConfs';
import PageFlip from '../components/PageFlip';
import listJson from './list-json';
import { TouchableOpacity } from 'react-native-gesture-handler';
type RespoListProps = any;
class RespoList extends Component<RespoListProps>{
constructor(props: RespoListProps){
super(props);
}
render(){
return (
<View style={styles.engine}>
<View style={{width: DeviceConfs.sWidth, height: 42,
flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'}}>
<TouchableOpacity onPress={()=>{this.props.navigation.pop()}} activeOpacity = {0.8}
style={{flexDirection:'row', alignItems: 'center', width:DeviceConfs.sWidth * 0.3}}>
<Image source={ImgConfs.ic_goback} resizeMode={'contain'}
style={{width: 38, height: 38}}/>
<Text style={{color: '#444', fontWeight: 'bold', fontSize: 14, alignSelf: 'center', marginLeft: -6}}>{'返回'}</Text>
</TouchableOpacity>
<View style={{width:DeviceConfs.sWidth * 0.3, alignItems: 'center', justifyContent:'center'}}>
<Text style={{color: '#333', fontWeight: 'bold', fontSize: 18}}>{'库存列表'}</Text>
</View>
<View style={{width:DeviceConfs.sWidth * 0.3}}/>
</View>
<View style={{height:4, width: DeviceConfs.sWidth, backgroundColor: '#f4f4f4'}}/>
<PageFlip onPreClick={()=>{}} onNextClick={()=>{}} />
<View style={{height:4, width: DeviceConfs.sWidth, backgroundColor: '#f4f4f4'}}/>
<FlatList
ref="flatList"
style={{flex:1}}
data={listJson}
showsVerticalScrollIndicator={false}
ItemSeparatorComponent={this.separatorComponent} // 分割线
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({item})=>this.renderItem(item)}
/>
<View style={{width: DeviceConfs.sWidth, height: 60,
backgroundColor: '#aa9a9a9a', position: 'absolute', left:0, top: DeviceConfs.sHeight - 80,
alignItems:'center', justifyContent: 'space-around', flexDirection: 'row'}}>
<TouchableOpacity style={{width: DeviceConfs.sWidth * 0.3, height: 42, borderRadius:4,
backgroundColor: '#16c36b',
alignItems:'center', justifyContent: 'center', flexDirection: 'row'}}>
<Text style={{color: 'white', fontWeight: 'bold', fontSize: 16}}>{'入 库'}</Text>
</TouchableOpacity>
<TouchableOpacity style={{width: DeviceConfs.sWidth * 0.3, height: 42, borderRadius:4,
backgroundColor: '#ff5558',
alignItems:'center', justifyContent: 'center', flexDirection: 'row'}}>
<Text style={{color: 'white', fontWeight: 'bold', fontSize: 16}}>{'出 库'}</Text>
</TouchableOpacity>
</View>
</View>)
}
_keyExtractor = (item: ResItem, index: number) => String(index)
renderItem = (item: ResItem)=>{return <RespertoryItem {...item}/>}
separatorComponent(){
return <View style={{height: 1, backgroundColor: '#f4f4f4'}}/>
}
}
export default RespoList;
const styles = StyleSheet.create({
engine: {
flex:1,
alignItems:'center',
backgroundColor: 'white'
}
});
//Types-list.ts
type ImageRequireSource = number;
export interface ResItem {
carIcon: ImageRequireSource;
carSoldIcon : string;
carName : string;
frontGlass : string;
behindGlass : string;
isSold : boolean;
isLast : boolean;
}
文章参考:
https://medium.com/@vnbnews.vn/reactnative-react-navigation-error
https://www.jianshu.com/p/618e644f6734