React Native入门及一些踩过的坑

Posted Coding_the_world

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Native入门及一些踩过的坑相关的知识,希望对你有一定的参考价值。

 

集成步骤也可以参考react-native中文网,但是中间还是会遇到特殊情况,上面没有说明

一、安装node(不然npm的时候会报“不是内部命令”)

  npm是nodejs的一个子内容,所以要使用npm,就一定要先安装nodejs。安装方法其实没啥好说的,完全傻瓜化的,官网上下载安装包,一路next就完了。

  安装完了如何判断自己是否安装成功呢?

  你只需要在命令行窗口中输入命令:  

node -v    //查看node 的版本号

npm -v   //查看npm的版本号

二、安装react-native

执行以下命令,进行安装

npm install -g react-native-cli

三、创建package.json

在项目根目录下创建一个名为package.json。可以直接创建,也可以使用npm init创建


  "name": "MyRNTest",
  "version": "1.0.0",
  "description": "",
  "scripts": 
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  ,
  "dependencies": 
    "babel-preset-react-native": "^4.0.0",
    "react": "^16.0.0-alpha.6",
    "react-native": "^0.55.0",
    "react-native-update": "^4.0.6"
  ,
  "devDependencies": 
    "babel-jest": "21.2.0",
    "jest": "21.2.1",
    "react-test-renderer": "16.0.0-alpha.6"
  ,
  "jest": 
    "preset": "react-native"
  

四、配置 maven

在项目的 build.gradle 文件中为 React Native 添加一个 maven 依赖的入口,必须写在 "allprojects" 代码块中:

allprojects 
    repositories 
        maven 
            //url "$rootDir/node_modules/react-native/android"如果路径这样写,会下载最新版本RN
            url "$rootDir/../node_modules/react-native/android"
        
        ...
    
    ...

在你的 app 中 build.gradle 文件中添加 React Native 依赖

dependencies 
    implementation 'com.android.support:appcompat-v7:27.1.1'
    ...
    //如果要限制版本:implementation("com.facebook.react:react-native:0.55.0")  force = true 
    implementation "com.facebook.react:react-native:+" 
defaultConfig 
        ...

        ndk 
            abiFilters "armeabi-v7a", "x86"
        

    
    packagingOptions 
        exclude "lib/arm64-v8a/librealm-jni.so"
    

    //解决jsr302与jsr305版本冲突
    configurations.all 
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
    

五、配置权限

在 AndroidManifest.xml 清单文件中声明权限:

//网络权限
<uses-permission android:name="android.permission.INTERNET" />
//弹框权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

 

如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明:

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

六、RN组件

1.首先在项目根目录中创建一个空的index.js文件。(注意在 0.49 版本之前是 index.android.js 文件)

index.js是 React Native 应用在 Android 上的入口文件。而且它是不可或缺的!

2. 添加你自己的 React Native 代码,简单例子,网上都有,我这里举一个多入口引用的例子

import React,  Component  from 'react';
import 
  AppRegistry,
  Text,
    View
 from 'react-native';

import MyFirstRN from './myfirstrn'//填写对应myfirstrn.js路径,我这里在根目录下
import MySecondRN from './mysecondrn'//填写对应mysecondrn.js路径,我这里在根目录下

//注册:第一个字段可以认为是为RN中的页面添加映射,需要和你Activity中注册的名称一致
AppRegistry.registerComponent('MyRNActivity', () => MyFirstRN);
AppRegistry.registerComponent('MyRNActivity2', () => MySecondRN);

注意,一个RN页面只能对应注册一个名称,不然会被覆盖,例如:

AppRegistry.registerComponent('MyRNActivity', () => MyFirstRN);
AppRegistry.registerComponent('MyRNActivity2', () => MyFirstRN);
//此时,MyRNActivity2会对应MyFirstRN,MyRNActivity不会对应,你的Activity中如果注册MyRNActivity
//则会报红屏MyRNActivity未注册

myfirstrn.js和mysecondrn.js简单写了下,需要注意里面的class需要用export default修饰,不然import时会报错

import React,  Component  from 'react';
import 
  AppRegistry,
  Text,
  View
 from 'react-native';

export default class MyFirstRN extends Component 
  render() 
      return (
        <View >
          <Text >
            我是 MyFirstRN ReactNative//例子里MySecondRN就这里改了下
          </Text>
        </View>
      );
    
  

七、悬浮框权限(仅开发时用于看红屏报错)

如果你的应用会运行在 Android 6.0(API level 23)或更高版本,请确保你在开发版本中有打开悬浮窗(overlay)权限。你可以在代码中使用Settings.canDrawOverlays(this);来检查。之所以需要这一权限,是因为我们会把开发中的报错显示在悬浮窗中(仅在开发阶段需要)。在 Android 6.0(API level 23)中用户需要手动同意授权。具体请求授权的做法是在onCreate()中添加如下代码。其中OVERLAY_PERMISSION_REQ_CODE是用于回传授权结果的字段。

private final int OVERLAY_PERMISSION_REQ_CODE = 1;  // 任写一个值

...

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
    if (!Settings.canDrawOverlays(this)) 
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                   Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
    
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
            if (!Settings.canDrawOverlays(this)) 
                // SYSTEM_ALERT_WINDOW permission not granted
            
        
    
    mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );

八、调用RN页面

有两种方法:

1.你的Activity继承ReactActivity

public class MyRNActivity2 extends ReactActivity 
//public class MyRNActivity2 extends BaseReactActivity 
    @Nullable
    @Override
    protected String getMainComponentName() 
        return "MyRNActivity2";
    

2.你的Activity实现 DefaultHardwareBackBtnHandler 接口

public class MyRNActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler 

    private ReactRootView mReactRootView;

    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()

                .setApplication(getApplication())

                .setCurrentActivity(this)

                .setBundleAssetName("index.android.bundle")

                .setJSMainModulePath("index.android")//xxx.js
                .addPackage(new MainReactPackage())

                .setUseDeveloperSupport(true)

                .setInitialLifecycleState(LifecycleState.RESUMED)

                .build();

        // 注意这里的MyReactNativeApp必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "MyRNActivity", null);
        setContentView(mReactRootView);
    

    @Override
    public void invokeDefaultOnBackPressed() 
        if(mReactInstanceManager!=null)
            mReactInstanceManager.onBackPressed();
        else
            super.onBackPressed();
        
    
    @Override
    protected void onResume() 
        super.onResume();
        if(mReactInstanceManager!=null)
            mReactInstanceManager.onHostResume(this,this);
        

    


    @Override
    protected void onPause() 
        super.onPause();

        if(mReactInstanceManager!=null)
            mReactInstanceManager.onHostPause(this);
        
    


    @Override
    protected void onDestroy() 
        super.onDestroy();

        if(mReactInstanceManager!=null)
            mReactInstanceManager.onHostDestroy(this);
        
    

另外:如果是原生和RN混合页面,可以在布局中添加RN控件,在activity中findview出来

<com.facebook.react.ReactRootView
    android:id="@+id/test_js2"
    ....
/>
public class MyRNActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler 

    private ReactRootView mReactRootView,mReactRootView2;

    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_rn);

        mReactRootView = findViewById(R.id.test_js);
        mReactInstanceManager = ReactInstanceManager.builder()

                .setApplication(getApplication())

                .setCurrentActivity(this)//可以不需要此代码

                .setBundleAssetName("index.android.bundle")

                .setJSMainModulePath("index.android")//xxx.js
                .addPackage(new MainReactPackage())

                .setUseDeveloperSupport(true)

                .setInitialLifecycleState(LifecycleState.RESUMED)

                .build();

        // 注意这里的MyReactNativeApp必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "MyRNActivity", null);

    

    @Override
    public void invokeDefaultOnBackPressed() 
        if(mReactInstanceManager!=null)
            mReactInstanceManager.onBackPressed();
        else
            super.onBackPressed();
        
    
    @Override
    protected void onResume() 
        super.onResume();
        if(mReactInstanceManager!=null)
            mReactInstanceManager.onHostResume(this,this);
        

    


    @Override
    protected void onPause() 
        super.onPause();

        if(mReactInstanceManager!=null)
            mReactInstanceManager.onHostPause(this);
        
    


    @Override
    protected void onDestroy() 
        super.onDestroy();

        if(mReactInstanceManager!=null)
            mReactInstanceManager.onHostDestroy(this);
        
    

九、Application继承ReactApplication

public class MyApp extends Application implements ReactApplication 

    private ReactNativeHost mReactNativeHost = new ReactNativeHost(this) 

        @Override
        public boolean getUseDeveloperSupport() 
            return true;
        

        @Override
        protected String getJSMainModuleName() 
            return "index.android";
        

        @Override
        protected List<ReactPackage> getPackages() 
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage()
            );
        ;

        @Override
        public ReactNativeHost getReactNativeHost() 
            return mReactNativeHost;
        

        @Override
        public void onCreate() 
            super.onCreate();
            SoLoader.init(this,false);
        

十、生成.bundle和.map文件

在app/main下创建assets文件夹,然后Android Studio Terminal在执行。0.49之后的版本index.android.js用index.js

$ react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.b
undle --assets-dest app/src/main/res/
>npm start

十一、一些坑

1.RN页面首次加载时,会白屏一下,可以采用 预加载 的方法

2.调试时请确保电脑和手机在同一WiFi环境下,不要使用WiFi共享类的软件,那可能导致APP红屏报404

3.红屏报错调用不到.so文件,app目录下的build.gradle中没有添加ndk abiFilters "armeabi-v7a", "x86"

以上是关于React Native入门及一些踩过的坑的主要内容,如果未能解决你的问题,请参考以下文章

我们一起踩过的坑----react(antd)

谈谈出入React框架踩过的坑

项目级-使用Django做api踩过的坑...

程序员架构修炼:踩过的坑和经验总结故障复盘流程及模板

前端开发工具Brackets介绍,安装及安装Emme插件时踩过的坑

typescript+vue踩过的坑-常见报错