目录:
1.ios环境:
brew update && brew doctor
xcode-select --install
brew install node
brew install watchman
安装xcode;
启动 Xcode,并在Xcode > Preferences > Locations菜单中检查一下是否装有某个版本的Command Line Tools
https://reactnative.cn/docs/assets/GettingStartedXcodeCommandLineTools.png推荐一个安装homebrew地址
homebrew下载慢解决方案
设置xcode
2.安卓环境:
安装java-sdk
android-studio
Android Studio 需要 Java Development Kit [JDK] 1.8 或更高版本。你可以在命令行中输入 javac -version来查看你当前安装的 JDK 版本。
注:android-studio较复杂详细查看官网
3. 安装react-native官方脚手架:
npm install react-native-cli -g
- react-native init demo
- yarn
- yarn add react-navigation
- yarn add react-native-gesture-handler
- react-native link react-native-gesture-handler
- npm install react-native-vector-icons
- react-native link react-native-vector-icons
- npm install --save redux
- npm install --save react-redux
- npm install --save-dev redux-devtools
- npm add redux-thunk
在使用 React Navigation 的项目中,想要集成 redux 就必须要引入 react-navigation-redux-helpers 这个库。
npm install --save react-navigation-redux-helpers
import { createStackNavigator, createAppContainer } from "react-navigation";
const AppNavigator=createAppContainer(createStackNavigator({//路由
HomePage:{
screen:HomePage
},
Page1:{
screen:Page1,
navigationOptions:(navigation => ({
title:`页面名`
}))
},
}))
export default class App extends React.Component {
render() {
return ;
}
}
应用场景初始化app的时候使用,比如前几秒的广告或者logo
import {
createStackNavigator,
createAppContainer,
createSwitchNavigator,//切换路由导航
createMaterialTopTabNavigator, //顶部导航
createBottomTabNavigator, //底部导航
createDrawerNavigator,// 抽屉
DrawerItems,// 抽屉
} from "react-navigation";
const InitNavigator = createStackNavigator({// app初始化显示的路由
WelcomePage: {
screen: WelcomePage,
navigationOptions: {
header: null,
}
}
},{
navigationOptions: {
// header: null,// 可以通过将header设为null 来禁用StackNavigator的Navigation Bar
}
})
const MainNavigator = createStackNavigator({// 业务路由
WelcomePage: {
screen: HomePage,
navigationOptions: {
header: null,
}
},
DetailPage: {
screen: DetailPage,
navigationOptions: {
title: 'DetailPage',
headerBackTitle: null
// header: null,
}
},
})
export const AppNavigator = createAppContainer(createSwitchNavigator({
Init: InitNavigator,
Main: MainNavigator,
}, {
initialRouteName: 'Init',
}))
export default class App extends React.Component {
render() {
return <AppNavigator/>;
}
}
底部导航
import MaterialIcons from 'react-native-vector-icons/MaterialIcons'// 图标库
const AppBottomNavigator = createBottomTabNavigator({////下面bar
PopularPage:{
screen:PopularPage,
navigationOptions:{
tabBarLabel:"最热",
tabBarIcon:({tintColor,focused})=>(
<MaterialIcons
name={"whatshot"}
size={26}
style={{
color:tintColor
}}
/>)
}
},
....
},
{
tabBarOptions: {
tabStyle: {
minWidth: 50
},
upperCaseLabel: false,//是否使标签大写,默认为true
scrollEnabled: true,//是否支持 选项卡滚动,默认false
// activeTintColor: 'white',//label和icon的前景色 活跃状态下(选中)
// inactiveTintColor: 'gray',//label和icon的前景色 活跃状态下(未选中)
style: {
backgroundColor: '#678',//TabBar 的背景颜色
},
indicatorStyle: {
height: 2,
backgroundColor: 'white',
},//标签指示器的样式
labelStyle: {
fontSize: 13,
marginTop: 6,
marginBottom: 6,
},//文字的样式
},
}
)
顶部导航
const AppTopNavigator=createMaterialTopTabNavigator({//上面bar
Page1: {
screen: Page1,
navigationOptions: {
tabBarLabel: 'java',
}
},
Page2: {
screen: Page2,
navigationOptions: {
tabBarLabel: 'android',
}
},
Page3: {
screen: Page4,
navigationOptions: {
tabBarLabel: 'ios',
}
},
},
{
tabBarOptions: {
tabStyle: {
minWidth: 50
},
upperCaseLabel: false,//是否使标签大写,默认为true
scrollEnabled: true,//是否支持 选项卡滚动,默认false
// activeTintColor: 'white',//label和icon的前景色 活跃状态下(选中)
// inactiveTintColor: 'gray',//label和icon的前景色 活跃状态下(未选中)
style: {
backgroundColor: '#678',//TabBar 的背景颜色
},
indicatorStyle: {
height: 2,
backgroundColor: 'white',
},//标签指示器的样式
labelStyle: {
fontSize: 13,
marginTop: 6,
marginBottom: 6,
},//文字的样式
},
}
)
export default class HomePage extends Component{
render() {
const {navigation} = this.props;
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to HomePage</Text>
<Button
title={"gopage1"}
onPress={()=>{
navigation.navigate("Page1",{name:"动态的"})
}}
/>
<Button
title={"goback"}
onPress={()=>{
navigation.goBack();
}}
/>
</View>
);
}
}
//目标页面获取值,setParams是改变当前页面的params
const {navigation} = this.props;
const {state, setParams} = navigation;
const {params} = state;
import React, {Component} from 'react';
import {Provider} from 'react-redux';
import AppNavigator from './navigation/AppNavigators';
import store from './store'
type Props = {};
export default class App extends Component<Props> {
render() {
/** * 将store传递给App框架 */
return <Provider store={store}>
<AppNavigator/>
</Provider> }
}
文件输出口,store和navigation输出配置到这个页面
import { onThemeChange,onShowMyName } from './theme'
export default {
onThemeChange,
onShowMyName
}
输出事件的操作
import Types from '../../action/types';
const defaultState = {
theme: "blue",
name: "no name"
}
export default function onAction(state =defaultState, action ){
switch (action.type){
case Types.THEME_CHANGE:
return {
...state,
theme: action.theme
};
case Types.NAME_CHANGE:
return {
...state,
name: action.name
};
default:return state;
}
}
js/reducer/index.js=>
import {combineReducers} from 'redux'
import theme from './theme'
import {rootCom, RootNavigator} from '../navigation/AppNavigators';
//1.指定默认state,获取路由信息
const navState = RootNavigator.router.getStateForAction(RootNavigator.router.getActionForPathAndParams(rootCom));
/** * 2.创建自己的 navigation reducer, */
const navReducer = (state = navState, action) => {
const nextState = RootNavigator.router.getStateForAction(action, state);
// 如果`nextState`为null或未定义,只需返回原始`state`
return nextState || state;
};
/** * 3.合并reducer * @type {Reducer | Reducer} */
const index = combineReducers({
nav: navReducer,
theme: theme,
});
export default index;
修改数据,合并所有reducer
import {applyMiddleware, createStore} from 'redux'
import thunk from 'redux-thunk'
import reducers from '../reducer'
import {middleware} from '../navigation/AppNavigators'
const logger = store => next => action =>{ // 自定义中间件
if( typeof action === 'function' ) {
} else {
// console.log("action",action)
}
const resut =next( action );
// console.log("state",store.getState())
}
const middlewares = [
middleware,
logger,
thunk
];
/** * 创建store */
export default createStore(reducers, applyMiddleware(...middlewares));
创建store
1.配置Navigation
import React from 'react';
import {createStackNavigator, createSwitchNavigator} from 'react-navigation';
import {connect} from 'react-redux';
import {createReactNavigationReduxMiddleware, createReduxContainer} from 'react-navigation-redux-helpers';
export const rootCom = 'Init';//设置根路由
export const RootNavigator = createSwitchNavigator({
...
});
/** * 1.初始化react-navigation与redux的中间件, * 该方法的一个很大的作用就是为reduxifyNavigator的key设置actionSubscribers(行为订阅者) * 设置订阅者@https://github.com/react-navigation/react-navigation-redux-helpers/blob/master/src/middleware.js#L29 * 检测订阅者是否存在@https://github.com/react-navigation/react-navigation-redux-helpers/blob/master/src/middleware.js#L97 * @type {Middleware} */
export const middleware = createReactNavigationReduxMiddleware(
state => state.nav,
'root'
);
/** * 2.将根导航器组件传递给 reduxifyNavigator 函数, * 并返回一个将navigation state 和 dispatch 函数作为 props的新组件; * 注意:要在createReactNavigationReduxMiddleware之后执行 */
const AppWithNavigationState = createReduxContainer(RootNavigator, 'root');
/** * State到Props的映射关系 * @param state */
const mapStateToProps = state => ({
state: state.nav,//v2
});
/** * 3.连接 React 组件与 Redux store */
export default connect(mapStateToProps)(AppWithNavigationState);
import {combineReducers} from 'redux'
import theme from './theme'
import {rootCom, RootNavigator} from '../navigator/AppNavigators';
//1.指定默认state
const navState = RootNavigator.router.getStateForAction(RootNavigator.router.getActionForPathAndParams(rootCom));
/** * 2.创建自己的 navigation reducer, */
const navReducer = (state = navState, action) => {
const nextState = RootNavigator.router.getStateForAction(action, state);
// 如果`nextState`为null或未定义,只需返回原始`state`
return nextState || state;
};
/** * 3.合并reducer * @type {Reducer | Reducer} */
const index = combineReducers({
nav: navReducer,
theme: theme,
});
export default index;
3.配置store
import {applyMiddleware, createStore} from 'redux'
import thunk from 'redux-thunk'
import reducers from '../reducer'
import {middleware} from '../navigator/AppNavigators'
const middlewares = [
middleware,
];
/** * 创建store */
export default createStore(reducers, applyMiddleware(...middlewares));
4.在组件中应用
import React, {Component} from 'react';
import {Provider} from 'react-redux';
import AppNavigator from './navigator/AppNavigators';
import store from './store'
type Props = {};
export default class App extends Component<Props> {
render() {
/** * 将store传递给App框架 */
return <Provider store={store}>
<AppNavigator/>
</Provider> }
}
5.订阅state
import React from 'react';
import {connect} from 'react-redux';
class TabBarComponent extends React.Component {
render() {
return (
<BottomTabBar
{...this.props}
activeTintColor={this.props.theme}
/> );
}
}
const mapStateToProps = state => ({
theme: state.theme.theme,
});
export default connect(mapStateToProps)(TabBarComponent);
6.触发action改变state
import React, {Component} from 'react';
import {connect} from 'react-redux'
import {onThemeChange} from '../action/theme'
import {StyleSheet, Text, View, Button} from 'react-native';
type Props = {};
class FavoritePage extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>FavoritePage</Text> <Button
title="改变主题色"
onPress={() => {
// let {dispatch} = this.props.navigation;
// dispatch(onThemeChange('red'))
this.props.onThemeChange('#096');
}}
/> </View> );
}
}
const mapStateToProps = state => ({});
const mapDispatchToProps = dispatch => ({
onThemeChange: (theme) => dispatch(onThemeChange(theme)),
});
export default connect(mapStateToProps, mapDispatchToProps)(FavoritePage);
7.处理安卓物理返回键
import React, {Component} from 'react';
import {BackHandler} from "react-native";
import {NavigationActions} from "react-navigation";
import {connect} from 'react-redux';
import DynamicTabNavigator from '../navigator/DynamicTabNavigator';
import NavigatorUtil from '../navigator/NavigatorUtil';
type Props = {};
class HomePage extends Component<Props> {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
/** * 处理 Android 中的物理返回键 * https://reactnavigation.org/docs/en/redux-integration.html#handling-the-hardware-back-button-in-android * @returns {boolean} */
onBackPress = () => {
const {dispatch, nav} = this.props;
//if (nav.index === 0) {
if (nav.routes[1].index === 0) {//如果RootNavigator中的MainNavigator的index为0,则不处理返回事件
return false;
}
dispatch(NavigationActions.back());
return true;
};
render() {
return <DynamicTabNavigator/>;
}
}
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(HomePage);
// 1.android/app目录下,执行cmd命令
$ keytool -genkeypair -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
// 2.把签名配置加入到项目的 gradle 配置中编辑你项目目录下的android/app/build.gradle,添加如下的签名配置:
...
android {
...
defaultConfig { ... }
signingConfigs {
release {
if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
storeFile file('my-release-key.keystore')
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias my-key-alias
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
// 3. 配置打包命令到package.js,并执行
"scripts": {
...
"build_android": "cd android && ./gradlew assembleRelease",//打包
"clear_android": "./gradlew clear" // 重新打包需要先执行这个命令
}
// 4.针对不同的 CPU 架构生成 APK 以减小 APK 文件的大小
// 在android/app/build.gradle中来生成针对不同 CPU 架构的 APK。
- ndk {
- abiFilters "armeabi-v7a", "x86"
- }
- def enableSeparateBuildPerCPUArchitecture = false
+ def enableSeparateBuildPerCPUArchitecture = true
+
+ def enableProguardInReleaseBuilds = true
// 5. 生成的 APK 文件位于
android/app/build/outputs/apk/release/app-release.apk,
它已经可以用来发布了。
https://www.jianshu.com/p/5bdce8da4d88
安卓开发推荐使用真机调试(打开开发者选项,),加react-native官方启动命令:react-native run-android(adb devices 可以查看是否有可用的安卓模拟器)
ios开发推荐使用,打开xcode,进行调试(真机调试较慢,react-native官方启动命令react-native run-ios:又慢又会启动失败(ノへ ̄、))
*检测文件是报错,更新电脑不更新代码(出现场景,打开项目就报错了):关闭一下终端,用xcode(or react-native run-android)重启软件
react-navigation:createAppContainer独立页面是用的时候需要加入
Invariant Violation: View config not found for name tabNavigator(有问题的变量名). Make sure to start component names with a capital letter:
有问题的变量名(首字母大写)
*引入的包出现问题的时候:https://github.com/facebook/react-native/issues/4968
没有正确引入报错的时候(一般出现在依赖的依赖需要被页面导入时)比如:
https://stackoverflow.com/questions/52071280/error-while-running-react-native-app?r=SearchResults
*用React native编译IOS 报错:Application AwesomeProject has not been registered
解决:控制台窗口,关闭xcode,重新编译
检查文件路径,参数是否正确
https://www.jianshu.com/p/17ce8f0ad542
AwesomeProject(简单react-navigation使用包括bottom,top,switch,navigator;高性能列表FlatList,)
rnNavigationText(高阶react-navigation使用)
rnReduxTest(react-navigation+redux如何使用开发;Fetch使用;AsyncStorage离线缓存;封装离线缓存框架等)
ps:点击鼠标左键,进入下载页