• Android原生项目接入RN发现今年React Native发展的挺好了,已经有很多公司开始使用RN来开发,我看慕课网也出了好多RN的视频以及实战课程。之前我也自学了RN,感觉上手入门还是挺快的,也打算继续学习下去。下面开始...

    发现今年React Native发展的挺好了,已经有很多公司开始使用RN来开发,我看慕课网也出了好多RN的视频以及实战课程。之前我也自学了RN,感觉上手入门还是挺快的,也打算继续学习下去。下面开始切入正题:

    假如你的Android原生项目已经写了很多,接下来想使用RN实现一些页面功能,那么该怎么接入呢,其实React Native中文网也有参考,但是我当时按照那篇文章来操作还是有些问题的,感觉不适合初学者来使用,接下来我打算记录一些我自己的接入过程。希望能给一些正在搞这个的朋友作出一些参考

    接入的前提条件:

    • 已有Android原生的工程
    • RN环境已经搭建好

    本篇文章的所记录的知识点有:

    • Android工程加载RN页面
    • RN来调用原生的方法,如果需要返回结果,则可以回调

    先大致浏览一下,接入RN之后Android工程的样子:

    接入工程图

    接下来开始实现接入

    • 步骤一: 用android studio打开已经创建好的Android工程,然后在Terminal中执行一下命令:

      1. npm init
      2. npm install –save react
      3. npm install –save react-native
      4. curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

      说明,在创建 npm init的时候,需要输入name、version等值,这里可以随意先输入一下,貌似在输入name的值只能用英文的小写字母表示,其实这个无所谓的,可以将其他的React Native工程中的package.json文件Copy过来,将里面的name等值改一下就ok了,还省事。 其他3个命令,依次敲回车执行即可。然后再从React Native工程中Copy一份index.android.js,注意的是,需要将AppRegistry.registerComponent('RNComponent', () => RNComponent); 第二个参数与package.json的name值保持一致(我这里改的是RNComponent,这个名字可以起别的也行)

    • 步骤二:这样React Native的工作差不多完成了,然后Android端需要创建一个Activity来装载所有的RN页面,这里我创建了MyReactActivity。在创建之前,需要在Android中添加一些依赖,否则用到一些类找不到,下面先开始配置Android工程

      step1. 在整个工程的build.gradle中添加 :

      allprojects {
              repositories {
      
                  mavenLocal()
                  jcenter()
                  maven {
                      // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
                      url "$rootDir/node_modules/react-native/android"
                  }
              }
          }
      
          task clean(type: Delete) {
              delete rootProject.buildDir
          }

      step2. 在moudle的build.gradle中添加compile "com.facebook.react:react-native:+" 具体参考我的builde.gradle配置,如下所示

      android {
          compileSdkVersion 25
          buildToolsVersion "25.0.2"
          defaultConfig {
              applicationId "com.reactnative"
              minSdkVersion 16
              targetSdkVersion 25
              versionCode 1
              versionName "1.0"
              testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
          }
      
          splits {
              abi {
                  reset()
                  enable true
                  universalApk true  // If true, also generate a universal APK
                  include "armeabi-v7a", "x86"
              }
          }
          buildTypes {
              release {
                  minifyEnabled false
                  proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
              }
          }
          configurations.all {
              resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
          }
      }
      
      dependencies {
          compile fileTree(dir: 'libs', include: ['*.jar'])
          androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
              exclude group: 'com.android.support', module: 'support-annotations'
          })
          compile 'com.android.support:appcompat-v7:25.0.1'
          testCompile 'junit:junit:4.12'
      
          compile "com.facebook.react:react-native:+"  // From node_modules
      }
      
    • 紧接着上面的步骤二,开始创建MyReactActivity,代码如下;

    import com.facebook.react.ReactActivity;
    
    public class MyReactActivity extends ReactActivity{
    
        @Override
        protected String getMainComponentName() {
            return "RNComponent";
        }
    }

    还有一种创建方式,就是下面这样的,其中这两种创建的MyReactActivity都是可以的,因为ReactActivity也是实现DefaultHardwareBackBtnHandler接口。

    public class MyReactActivity extends Activity 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())
                    .setBundleAssetName("index.android.bundle")
                    .setJSMainModuleName("index.android")
                    .addPackage(new MainReactPackage())
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
    
    
            mReactRootView.startReactApplication(mReactInstanceManager, "RNComponent", null);
    
            setContentView(mReactRootView);
        }
    
        @Override
        public void invokeDefaultOnBackPressed() {
            super.onBackPressed();
        }
    }
    • 接下来开始创建 MainApplication,代码如下
    
    public class MainApplication extends Application implements ReactApplication {
    
      private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    
    
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }
    
        @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, /* native exopackage */ false);
      }
    }
    • ok,最后在AndroidManifest文件中,添加一些权限,以及声明MainApplication跟MyReactActivity
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.reactnative">
    
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
        <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
    
        <application
            android:name=".MainApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
    
    
            <activity
                android:name=".MyReactActivity"
                android:configChanges="orientation|screenSize"
                android:theme="@style/NoActionBar"
                />
    
            <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
    
    
        </application>
    
    </manifest>

    这里需要说明一下,在声明MyReactActivity的时候,需要给它指定一个没有ActionBar的样式,在styles.xml中作修改:

      <style name="NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>

    到此为止,不出意外,一般都能正常加载RN页面,效果如下:

    效果图

    到这里 简单的接入已经完成了,但是正常项目中,接入RN之后,RN肯定还要调用原生的一些方法,并且希望能拿到结果。比方说,RN想要得到系统相册某些图片的路径,那么Android端就能提供查找的方法,并且将这个结果回调给RN

    接下来开始实现 交互的过程

    • 第一步,需要写个类来继承ReactContextBaseJavaModule
    package com.reactnative;
    
    import android.content.Context;
    import android.text.TextUtils;
    import android.widget.Toast;
    import com.facebook.react.bridge.Callback;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.bridge.ReactContextBaseJavaModule;
    import com.facebook.react.bridge.ReactMethod;
    import com.facebook.react.uimanager.IllegalViewOperationException;
    
    public class MyNativeModule extends ReactContextBaseJavaModule {
    
        private Context mContext;
    
        public MyNativeModule(ReactApplicationContext reactContext) {
            super(reactContext);
    
            mContext = reactContext;
        }
    
        @Override
        public String getName() {
    
            //返回的这个名字是必须的,在rn代码中需要这个名字来调用该类的方法。
            return "MyNativeModule";
        }
    
        //函数不能有返回值,因为被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数或者发送信息给rn那边。
    
        @ReactMethod
        public void rnCallNative(String msg) {
    
            Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
        }
    
        /**
         * 创建给js调用的方法 将网络请求的结果以回调的方式传递给js
         *
         * @param url
         * @param callback
         */
        @ReactMethod
        public void getResult(String url, final Callback callback) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
    //                    模拟网络请求数据的操作
                        String result = "我是请求结果";
                        callback.invoke(true, result);
    
                    } catch (Exception e) {
    
                    }
                }
            }).start();
        }
    
        @ReactMethod
        public void tryCallBack(String name, String psw, Callback errorCallback, Callback successCallback) {
            try {
                if (TextUtils.isEmpty(name) && TextUtils.isEmpty(psw)) {
                    // 失败时回调
                    errorCallback.invoke("user or psw  is empty");
                }
                // 成功时回调
                successCallback.invoke("add user success");
            } catch (IllegalViewOperationException e) {
                // 失败时回调
                errorCallback.invoke(e.getMessage());
            }
        }
    
        /**
         * 回调给android端的数据
         *
         * @param callback
         */
        @ReactMethod
        public void renderAndroidData(Callback callback) {
            callback.invoke("android data");
        }
    }

    说明,这里第一个需要注意的地方是getName()方法,返回的这个别名,将来在RN的js中需要用到这个别名来调原生的方法。第二个地方,凡是需要RN调用的方法,都需要加@ReactMethod 注解。第三个地方,原生提供的方法的返回值类型都是void类型,比较简单的如rnCallNative(String msg) , RN那边调用,就是吐司一下。如果需要返回结果就需要回调,如renderAndroidData(Callback callback)

    ok,原生方法算是写好了,接下来需要创建一个类来实现ReactPackage,将我们创建的类添加进原生模块列表中。如下所示:

    public class MyReactPackage implements ReactPackage {
    
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    
            List<NativeModule> modules = new ArrayList<>();
            //将我们创建的类添加进原生模块列表中
            modules.add(new MyNativeModule(reactContext));
            return modules;
        }
    
    
        @Override
        public List<Class<? extends JavaScriptModule>> createJSModules() {
    
            //返回值需要修改
            return Collections.emptyList();
        }
    
    
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    
            //返回值需要修改
            return Collections.emptyList();
        }
    }

    还需要在MainApplication中,将我们创建的包管理器给添加进来 ,如下所示:

    public class MainApplication extends Application implements ReactApplication {
    
        private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    
    
            @Override
            public boolean getUseDeveloperSupport() {
                return BuildConfig.DEBUG;
            }
    
            @Override
            protected List<ReactPackage> getPackages() {
                return Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        //将我们创建的包管理器给添加进来
                        new MyReactPackage()
                );
            }
        };
    
        @Override
        public ReactNativeHost getReactNativeHost() {
            return mReactNativeHost;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            SoLoader.init(this, /* native exopackage */ false);
        }
    }

    这样的话,原生模块算是写好了,接下来RN来调用Native方法,将index.android.js中可以这样调用:

    • 首先 import { NativeModules} from ‘react-native’;

    • 调用原生方法可以这么去写NativeModules.MyNativeModule.rnCallNative('调用原生方法的Demo');

    展示 index.android.js 全部代码;

    export default class RNComponent extends Component {
    
        // 构造
        constructor(props) {
            super(props);
            // 初始状态
            this.state = {
                title: '',
            };
        }
    
         render() {
                 tryCall = () => {
                     var rnToastAndroid = NativeModules.MyNativeModule;
                     rnToastAndroid.tryCallBack("luo", "131", (errorCallback) => {
                             alert(errorCallback)
                         },
                         (successCallback) => {
                             alert(successCallback);
                         });
                 };
                 androidback = () => {
    
                     var ANdroidNative = NativeModules.MyNativeModule;
                     ANdroidNative.renderAndroidData((Callback) => {
                         alert(Callback);
    
                     });
                 };
    
                 return (
    
                     <View style={styles.container}>
                         <Text style={styles.welcome}
                               onPress={this.call_button.bind(this)}
                         >
                             React Native 调用原生方法!
                         </Text>
                         <Text style={styles.instructions}
                               onPress={()=>androidback()}
                         >
                             获得android回调的数据
                         </Text>
                         <Text style={styles.instructions}>
    
                             {NativeModules.MyNativeModule.rnCallNative(this.state.title)}
                         </Text>
    
                         <Text style={styles.instructions} onPress={()=>tryCall()}>
                             trycallAndroid
                         </Text>
                     </View>
                 );
             }
    
             call_button() {
    
                 NativeModules.MyNativeModule.rnCallNative('调用原生方法的Demo');
             }
    
    }
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: '#F5FCFF',
        },
        welcome: {
            fontSize: 20,
            textAlign: 'center',
            margin: 10,
        },
        instructions: {
            textAlign: 'center',
            color: '#333333',
            marginBottom: 5,
        },
    });
    
    AppRegistry.registerComponent('RNComponent', () => RNComponent);
    

    看看整个工程目录:

    整个工程目录

    最后运行效果:

    最后运行效果

    到此为止,Native接入RN,以及与RN的交互基本上介绍完了,如果还不是很明白,可以下载demo,结合本篇文章应该是可以搞定的。Demo地址github

    展开全文
  • 最近工作上的项目要接入react-native技术,因此需要把原生项目接入到rn的配置环境中,整个过程遇到了不少坑,rn以后会是个趋势,也许慢慢会有越来越多的人需要将现有项目接入rn,估计在配置的时候都会遇到一些坑,这...

    最近工作上的项目要接入react-native技术,因此需要把原生项目接入到rn的配置环境中,整个过程遇到了不少坑,rn以后会是个趋势,也许慢慢会有越来越多的人需要将现有项目接入rn,估计在配置的时候都会遇到一些坑,这篇文章记录下整个配置的过程,既为提自己做个记录,也希望能帮到有同样项目需求的人。

    搭建开发环境

    开发环境的搭建 这部分只要跟着官方文档里就行,一般都会比较顺利。

    完成rn环境配置

    进入项目跟目录,使用命令行顺序执行一下三个命令

    npm init
    npm install –save react react-native
    curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

    在运行过程中我发现自己电脑没有curl这个指令,直接到这个地址 选择你需要的版本下载下来就行

    完成上面命令之后你会发现当前目录下多了一个node-mudules文件夹还有一个package.json文件,在package.json文件的scripts部分增加

    "start": "node node_modules/react-native/local-cli/cli.js start"

    如图
    在工程根目录生成新建index.android.js文件,并拷贝如下代码进入,它将作为原生启动的rn代码

    'use strict';
    
    import React from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View
    } from 'react-native';
    
    class HelloWorld extends React.Component {
      render() {
        return (
          <View style={styles.container}>
            <Text style={styles.hello}>Hello, World</Text>
          </View>
        )
      }
    }
    var styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
      },
      hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
    });
    
    AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

    原生项目配置

    在app的build.gradle增加配置

    dependencies {
         ...
         compile "com.facebook.react:react-native:+" // From node_modules.
     }

    在整个工程的build.gradle里增加react-native仓库配置

    allprojects {
        repositories {
            ...
            maven {
                // All of React Native (JS, Android binaries) is installed from npm
                url "$rootDir/node_modules/react-native/android"
            }
        }
        ...
    }

    上面的$rootDir代表你工程根目录, 有些工程根目录和node_modules的位置关系跟上面写的不一样,执行根据位置关系修改。
    保证你的项目有访问网络的权限

    <uses-permission android:name="android.permission.INTERNET" />
    

    添加原生代码

    按照官方文档新建一个Activity

    public class MyReactActivity extends Activity 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())
                    .setBundleAssetName("index.android.bundle")
                    .setJSMainModuleName("index.android")
                    .addPackage(new MainReactPackage())
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
            mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);
    
            setContentView(mReactRootView);
        }
    
        @Override
        public void invokeDefaultOnBackPressed() {
            super.onBackPressed();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
    
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostPause();
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostResume(this, this);
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostDestroy();
            }
        }
    
        @Override
         public void onBackPressed() {
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onBackPressed();
            } else {
                super.onBackPressed();
            }
        }
    }

    并配置对应Androidmainfiest

    <activity
                android:name=".ui.activity.MyReactActivity"
                android:screenOrientation="portrait"
                />

    这个时候基本已经按照官方文档提供的说明完成了配置,然后一点gradle运行,发现报了版本问题,原来项目的最低版本不能满足rn的要求

    但上面也给出了解决方案,给uses-sdk增加相应overrideLibrary说明

    <uses-sdk
        tools:overrideLibrary="com.facebook.react"
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />

    然后继续打算运行又报错了
    这里写图片描述
    这是因为react-native的res使用到了23sdk的资源,因此编译的sdk要求是23,因此修改sdk版本

    compileSdkVersion 23
    buildToolsVersion '23.0.3'

    当我们修改了编译的sdk,可能会导致以前的一些sdk调用的方法不存在或者不兼容之类的,这个问题根据各自项目自己去修改,比如我的项目就遇到Notification的setLatestEventInfo不存在,修改相应的sdk 23对应的方法,还有一个问题是AndroidHttpClient这个类在android 23已经被废弃,针对这个问题,在build.gradle增加

    android {
        useLibrary 'org.apache.http.legacy'
    }

    同样的useLibrary这个gradle语句对gradle版本也有要求,我们项目本身的gradle1.2.3,这句配置需要升级到最新版本2.0.0,到整个工程的build.gradle修改gradle版本

    dependencies {
            classpath 'com.android.tools.build:gradle:2.1.3'
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }

    修改完运行gradle提示这个问题
    这里写图片描述
    同样根据提示修改,在gradle.properties增加

    android.useDeprecatedNdk=true

    同时提示要将gradle版本至少支持2.14.1同样去修改gradle-wrapper.properites里面的gradle地址

    distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

    最后再来运行下,发现multiDex问题,估计是引入rn的一些方法导致方法数超了吧,这个就好解决了
    这里写图片描述
    在build.gradle配置

            multiDexEnabled true
    

    然后在application增加

     @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            MultiDex.install(this);
        }

    这次终于编译通过了。

    代码可以部署到设备上,然后在命令行输入npm start,然后启动调用自己的MyReactActivity,这里写图片描述大功告成。

    展开全文
  • 本篇文章记录了在已经创建好的原生项目上集成react-native的过程。 一、创建工程 我在桌面创建了一个工程,命名RNTest。 1_1.png 二、添加package.json文件 在RNTest目录下创建一个package.json或者直接从...

    本篇文章记录了在已经创建好的原生项目上集成react-native的过程。

    一、创建工程

    我在桌面创建了一个工程,命名RNTest。


    1_1.png

    二、添加package.json文件

    在RNTest目录下创建一个package.json或者直接从别的react-native项目中复制过来。

    {
        "name": "RNTest",
        "version": "0.0.1",
        "private": true,
        "scripts": {
            "start": "node node_modules/react-native/local-cli/cli.js start",
            "test": "jest"
        },
        "dependencies": {
            "react": "~15.4.1",
            "react-native": "0.42.0"
        },
        "devDependencies": {
            "babel-jest": "20.0.3",
            "babel-preset-react-native": "2.1.0",
            "jest": "20.0.4",
            "react-test-renderer": "~15.4.1"
        },
        "jest": {
            "preset": "react-native"
        }
    }

    2_1.png

    三、安装react-native模块

    在终端cd到项目目录,然后执行npm install


    3_1.png

    3_2.png

    四、导入react-native框架

    1.创建一个新的文件夹,命名为Librarys,到时候要把rn的项目拉进文件夹中。


    4_1.png

    2.把rn的项目拉进文件夹中

    这里要拉的比较多也比较杂,先拉React.xcodeproj文件。(路径如图)


    4_2.png

    再拉node_modules/react-native/Libraries下的文件


    4_3.png

    4_4.png

    3.Link Binary With Libraries中添加.a库


    4_5.png


    (点击+按钮 全部添加后,在删除tvOS的就好,最后别忘了加上libstdc++.tbd)
    (ps:这里我漏删除了一个tvOS的静态库,导致运行出错,删了就行,懒得再截图了。。。)

    4.在Edit Scheme的Build中添加React

    向Edit Scheme的Build中添加React,并拖拽到最上位置,并取消勾选Parallelize Build选项。这一步很关键,因为项目需要先编译React.a文件。


    4_6.png

    4_7.png

    五、最后的配置

    Build SettingsOther Linker Flags设置为 -ObjC
    Header Search Paths设置为/react-native/React路径,并设置为 recursive。


    5_1.png

    六、创建index.ios.js文件

    创建index.ios.js文件,到时候,rn代码要写在这里。当然,放在node_modules同一个目录下就可以。


    6_1.png

    七、设置AppDelegate.h代码

    这里是为了获得rn的代码,从而相互传递数据

    #import "AppDelegate.h"
    #import <React/RCTRootView.h>
    #import <React/RCTBundleURLProvider.h>
    #import "ViewController.h"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
        RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                            moduleName:@"RNTest"
                                                     initialProperties:nil
                                                         launchOptions:nil];
        rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
    
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.rootViewController = [[UIViewController alloc] init];
        self.window.rootViewController.view = rootView;
    
        [self.window makeKeyAndVisible];
        return YES;
    }

    也不一定要写在这里,可以放在需要使用rn的VC中。

    八、使用了HTTPS协议进行传输

    为了能上网,在info.plist文件中添加一个字典类型的key为App Transport Security Settings。。。不说了

    九、运行


    8_1.png


    react.png

    前言&目录

    前两篇文章主要介绍了react-native的集成方法,本篇文章主要记录react-native的使用,包括:
    1.原生控制器添加react-native视图
    2.js向原生系统传值或事件
    3.原生系统向js传值或事件

    一、原生控制器添加react-native视图

    第一个使用例子很简单,说下要求:想要实现主控制器为原生控制器,点击后push到下一个控制器显示的是react-native视图。
    新建一个集成react-native后的项目,并新建两个控制器。既然要在第二个控制器中放上react-native视图,那么前面的代码都以往的开发一样。
    设置主视图

    //  AppDelegate.m
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        return YES;
    }

    第一个控制器设置跳转

    //  ViewController.m
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self.navigationController pushViewController:[[NextViewController alloc] init] animated:YES];
    }

    而在第二个控制器上放上加载js的代码。

    //  NextViewController.m
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.title = @"第二个VC";
    
        NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
        RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                            moduleName:@"NewRN"
                                                     initialProperties:nil
                                                         launchOptions:nil];
        rootView.frame = self.view.bounds;
        [self.view addSubview:rootView];
    }

    这样就实现了想在哪使用react-native就在哪使用。
    效果:


    效果一.gif


    (ps:react-native的界面暂时不管)

    二、js向原生系统传值或事件

    数据传递

    下面要实现的是,通过js向原生的程序传递数据。比如js里面的字符串要让程序打印出来。
    下面开始实现:
    新建一个继承NSObject且遵循RCTBridgeModule协议的类,这里命名为HelloWorld。

    //  HelloWorld.h
    #import <Foundation/Foundation.h>
    #import <React/RCTBridgeModule.h>
    @interface HelloWorld : NSObject <RCTBridgeModule>
    @end
    //  HelloWorld.m
    #import "HelloWorld.h"
    #import <UIKit/UIKit.h>
    #import <React/RCTEventDispatcher.h>
    #import <React/RCTConvert.h>
    
    @implementation HelloWorld
    RCT_EXPORT_MODULE();
    
    RCT_EXPORT_METHOD(sendStr:(NSString *)str)
    {
        NSLog(@"%@", str);
    }
    
    RCT_EXPORT_METHOD(sendArray:(NSArray *)arr)
    {
        NSLog(@"%@", arr);
    }
    
    RCT_REMAP_METHOD(sendParas, num:(nonnull NSNumber *)num str:(NSString *)str arr:(NSArray *)arr)
    {
        NSLog(@"%@ %@ %@", num, str, arr);
    }

    为了实现RCTBridgeModule协议,需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在js中访问这个模块的名字。如果你不指定,默认就会使用这个类的名字。
    通过RCT_EXPORT_METHOD()宏来实现js调用的oc方法。也就是说,在宏中声明一个方法,js中能获取到这个方法,并且调用,从而向原生传值。
    下面是js代码:

    //  js
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      Button,
      NativeModules,
      Image
    } from 'react-native';
    
    
    export default class NewRN extends Component {
    
    
      StrOnPress()
      {
                    let HelloWorld = NativeModules.HelloWorld;
                    HelloWorld.sendStr('这是传过来的字符');
      }
    
      ArrOnPress()
      {
                   let HelloWorld = NativeModules.HelloWorld;
                   var array = new Array()
                   array[0] = "this"
                   array[1] = "is"
                   array[2] = "array"
                   HelloWorld.sendSomeThing(array);
      }
      parasOnPress()
      {
                   let HelloWorld = NativeModules.HelloWorld;
                   var array = new Array()
                   array[0] = "this"
                   array[1] = "is"
                   array[2] = "array"
                   HelloWorld.sendParas(2, '传过来的字符', array);
      }
    
      render()
      {
        return (
          <View style={styles.container}>
            <View style={{marginTop:10}}>
                <Button onPress={this.StrOnPress.bind(this)} title="传递字符" />
            </View>
            <View style={{marginTop:10}}>
                <Button onPress={this.ArrOnPress.bind(this)} title="传递数组" />
            </View>
            <View style={{marginTop:10}}>
                <Button onPress={this.parasOnPress.bind(this)} title="多参数按钮" />
            </View>
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },
      welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
      instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
      },
    });
    
    AppRegistry.registerComponent('NewRN', () => NewRN);

    可以拿出一个来看:

    // rn控件并添加响应
    <View style={{marginTop:10}}>
           <Button onPress={this.StrOnPress.bind(this)} title="传递字符" />
    </View>
    // js响应方法
      StrOnPress()
    {
                    let HelloWorld = NativeModules.HelloWorld;
                    HelloWorld.sendStr('这是传过来的字符');
    }
    // oc方法
    RCT_EXPORT_METHOD(sendStr:(NSString *)str)
    {
        NSLog(@"%@", str);
    }

    通过代码可以看到通过点击rn的按钮执行StrOnPress()方法,然后获取到HelloWorld类的sendStr方法,并调用,然后就会打印出来。
    效果:


    效果二.gif

    响应事件

    如果当点击rn中的按钮时,想要再跳到下一个控制器,该怎么做。
    我试过给当前这个HelloWorld添加了协议,让第二个控制器遵守协议,当点击按钮时控制器实现协议方法,在协议方法中跳转,但是失败了。
    也试过给HelloWorld添加block,并在block中跳转,也失败了。
    失败的原因在于,在控制器中初始化HelloWorld的实例和在

    RCT_EXPORT_METHOD(sendStr:(NSString *)str)
    {
        NSLog(@"%@", str);
    }

    方法中获得的self实例不是同一个。
    目前能想到的方法是,直接在这个HelloWorld类中实现跳转。

    RCT_EXPORT_METHOD(sendStr:(NSString *)str)
    {
        NSLog(@"%@", str);
        UINavigationController *nav = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
        UIViewController *vc = [[UIViewController alloc] init];
        vc.title = str;
        [nav pushViewController:vc animated:YES];
    }

    三、原生系统向js传值或事件

    要实现的是js传递两个数给原生,原生判断大小并返回结果。
    代码:

    RCT_REMAP_METHOD(compare, num1:(nonnull NSNumber *)num1 num2:(nonnull NSNumber *)num2 callback:(RCTResponseSenderBlock)callback)
    {
        NSString *result;
        result = num1>num2 ? @"num1大于num2" : @"num1不大于num2";
        NSArray *events = [NSArray arrayWithObjects:result,nil];
        callback(@[[NSNull null], events]);
    }
      compareOnPress()
      {
        let HelloWorld = NativeModules.HelloWorld;
        HelloWorld.compare(2, 3, (err, res) => {
          alert(res);
        });
      }
    
            <View style={{marginTop:10}}>
                <Button onPress={this.compareOnPress.bind(this)} title="比较按钮" />
            </View>

    效果:


    效果三.gif


    这里是通过RCTResponseSenderBlock来实现回调的。

    再放一个例子:

    RCT_REMAP_METHOD(printDate, date1:(nonnull NSNumber *)d1 date2:(nonnull NSNumber *)d2 event:(RCTResponseSenderBlock)callback)
    {
        NSString *resultStr;
        NSDate* dt1 = [RCTConvert NSDate:d1];
        NSDate* dt2 = [RCTConvert NSDate:d2];
        NSComparisonResult result = [dt1 compare:dt2];
        if (result==NSOrderedAscending) {
            resultStr = @"比较结果:开始时间小于结束时间";
        } else {
            resultStr = @"比较结果:开始时间大于结束时间";
        }
        NSArray *events = [NSArray arrayWithObjects:resultStr,nil];
        callback(@[[NSNull null], events]);
    }
    import React, { Component } from 'react';
    import {
        AppRegistry,
        StyleSheet,
        Text,
        View,
        Button,
        DatePickerIOS,
        NativeModules
    } from 'react-native';
    
    export default class NewRN extends Component {
        constructor(){
          super();
          this.state = {startDate: new Date(), endDate: new Date()};
        }
        onPressDateValidation() {
          var HelloWorld = NativeModules.HelloWorld;
          HelloWorld.printDate(this.state.startDate.getTime(), this.state.endDate.getTime(), (err, res) => {
            alert(res);
          });
        }
        onStartDateChange(date) {
          this.setState({startDate: date});
        }
        onEndDateChange(date) {
          this.setState({endDate: date});
        }
        render() {
                return (
              <View style={{marginTop:40}}>
    
                <DatePickerIOS
                  date={this.state.startDate}
                  mode='date'
                  onDateChange={this.onStartDateChange.bind(this)} />
                <DatePickerIOS
                  date={this.state.endDate}
                  mode='date'
                  onDateChange={this.onEndDateChange.bind(this)} />
                <Button onPress={this.onPressDateValidation.bind(this)} title="Compare" />
    
              </View>
                );
        }
    }
    
    AppRegistry.registerComponent('NewRN', () => NewRN);

    效果:


    效果四.gif

    IOS开发纪录

    如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

    赞赏支持


    作者:Jabber_YQ
    链接:http://www.jianshu.com/p/b0b8516fcbcf
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    展开全文
  • react-native和H5的通信

    2019-07-19 20:14:05
    首先如果你的项目中需要接入一个H5写的项目,但是这个服务有必须用到react-native中的服务比如打开摄像头,获取地理位置等等。但是这些数据在H5中是获取不到的,那么就需要和react-native通信,在react-native中获取...

    1.react-native 和 H5通信的情景

    首先如果你的项目中需要接入一个H5写的项目,但是这个服务有必须用到react-native中的服务比如打开摄像头,获取地理位置等等。但是这些数据在H5中是获取不到的,那么就需要和react-native通信,在react-native中获取到想要的数据,然后将数据返回给H5。

    2.实现方式

    (1).通过android原生和ios原生可以实现和H5的通信。
    (2).通过react-native中的webview来实现和H5通信。
    (3).通过第二种方式实现:
    在webview中onMessage是用来监听H5发送的消息的,我们可以在onMessage中接受到请求的数据。
    例如:

     <WebView   
     	onMessage={
     		(data)=>{console.log(data);}
     	} 
     />
    

    在 rn中通过webview的postMessage给H5返回结果。
    例如:

    <WebView   
         	ref={ (webview) => {this.web=webvew;} }
     />
         
    handleResponse=(response)=>{
    	this.web.postMessage(response);
    }
    

    H5中可以通过window.ReactNativeWebView.postMessage()向rn中发送消息。
    例如:

    function(request){
    	 window.ReactNativeWebView.postMessage(request);
    }
    
    展开全文
  • react-native页面的跳转

    2018-03-21 11:41:13
    react-native的页面跳转 引言 :react-native出来也有一段时间了,一直只是听说react-nativa是如何的好,能够实现跨平台(android、IOS).一直没有去主动交接它。直到最近,公司为了节省后期的维护成本,也同时将...

    react-native的页面跳转

    引言 :react-native出来也有一段时间了,一直只是听说react-nativa是如何的好,能够实现跨平台(android、IOS).一直没有去主动交接它。直到最近,公司为了节省后期的维护成本,也同时将现有的项目进行一次升级,然后决定用react-native重新开发一套。
    当然了,接触一门新的技术难免会遇到很多的难点。根据实际开发遇到的问题写点文章。巩固自己的同时也许能帮到别人。
    我学习的资料网[React Native 中文网](http://reactnative.cn/)
    学习前期一些属性(props)、状态(state)、样式(style)、布局(flexbox)看着敲敲代码就能比较好接受了。
    难点就是卡在页面的跳转了,虽然文档也提供了页面跳转的教程,但给我的感觉是一个页面自己在跳然后修改了一写属性值。(这并不能让我很满意,于是我就决定自己找资料写一个自己满意的)
    [参考地址](http://blog.csdn.net/youth_never_go_away/article/details/52572029)
    
    正题开始:先给大家上一组图(很惭愧,不会上传视频)。
    

    第一个界面
    第一个界面
    点击跳转的图片
    点击跳转的图片
    点击跳转的图片
    点击跳转的图片
    注:在android。处于主界面时,支持双击返回退出。在其他页面时,支持点击返回回到上一个界面。
    在实现界面跳转时需要提前了解的知识:

    1. navigater(导航器)
    2. scene(场景)
    3. route(路由)

      这三个概念也会在下面的代码中介绍到。

    代码部分

    程序的入口:index.ios.js

    import React, { Component } from 'react';
    import {
        AppRegistry,
    } from 'react-native';
    import SimpleComponent from './jsScene/SimpleComponent';
    
    export default class helloRN extends Component {
      render() {
        return (
            //显示组件
            <SimpleComponent />    
        );
      }
    }
    
    AppRegistry.registerComponent('helloRN', () => helloRN);

    入口代码非常简单,就是显示一个SimpleComponent的组件(不过你们要是照着敲时,注意文件夹的关系,这个很重要)
    组件SimpleComponent.js

    import React, { Component } from 'react';
    import { View, Text, Navigator } from 'react-native';
    import FirstPageComponent from './FirstPageComponent';
    
    export default class SimpleComponent extends Component {
      render() {
            //组件名字
            let defaultName = 'FirstPageComponent';
            //组件的Class用来实例化成<Component/>标签的
            let defaultComponent = FirstPageComponent;
            return (
                <Navigator
                    //这个指定了默认的页面,也就是启动app之后会看到界面的第一屏。 需要填写两个参数: name 跟 component。
                    //(注意这里填什么参数纯粹是自定义的,因为这个参数也是你自己发自己收,自己在renderScene方法中处理。
                    // 我们这里示例用了两个参数,但其实真正使用的参数只有component)
    
                    initialRoute={{ name: defaultName, component: defaultComponent }} //初始化场景
    
                    //页面跳转动画  可以返回多个动画  使用||返回
    
                    configureScene={(route) => {
                      return Navigator.SceneConfigs.HorizontalSwipeJump;    //设置场景的切换方式
                    }}
                    //渲染场景  route中就是我们自定义的 name 和 component
                    //navigator 就是Navigator对象
    
                    renderScene={(route, navigator) => {
                      let Component = route.component;
    
                      //Component 是route的component参数值  在路由中初始化的component的参数值是 defaultComponent
                      //所以 Component组件就是FirstPageComponent组件
    
                      return <Component {...route.params} navigator={navigator} />
                    }} />
            );
        }
    }
    

    这段代码里面的内容就比较复杂了,我就每个关键字逐一解释,主要的内容是return()中的内容。
    < Navigater />个人Navigater是所有组件的一个容器,所有的组件都会在Navigater中进行处理,后面会有代码进行很好的解释。
    initialRoute={{ name: defaultName, component: defaultComponent }},这段代码是初始化一个路由,每一个页面以route为单位在Navigater中活动(显示或移除)

    return Navigator.SceneConfigs.HorizontalSwipeJump; //界面的切换效果

        renderScene={(route, navigator) => {
                      let Component = route.component;
    
                      //Component 是route的component参数值  在路由中初始化的component的参数值是 defaultComponent
                      //所以 Component组件就是FirstPageComponent组件
    
                      return <Component {...route.params} navigator={navigator} />
                    }}

    这是最重要的一段代码,渲染一个场景,然后将渲染的场景(FirstPageComponent)返回(显示出来)。

    组件FirstPageComponent.js

    import React, { Component } from 'react';
    import {
      View,
      StyleSheet,
      Navigator,
      Text,
      BackAndroid,
      TouchableOpacity
    } from 'react-native'
    
    //(MyToast是本人桥接的android的Toast。实际使用的过程可以直接去掉,以免报错)
    import MyToast from './MyToast';
    
    // // 下一句中的ToastAndroid即对应上文
    // // public String getName()中返回的字符串
    // // 练习时请务必选择另外的名字!
    //
    // export default NativeModules.ToastAndroid;
    import SecondPageComponent from './SecondPageComponent';
    import ThirdPageComponent from './ThirdPageComponent';
    import FourthPageComponent from './FourthPageComponent';
    
    export default class FirstPageComponent extends Component{
      constructor(props){
        super(props);
        this.state = {};
        this.firstClick = 0;
        this.handleBack = this.handleBack.bind(this);
      }
    
      //生命周期方法。在组建第一次绘制完成后调用,通知组建已经加载完成。
      componentDidMount () {
        BackAndroid.addEventListener('hardwareBackPress', this.handleBack)  //增加手机物理返回键的监听
      }
    
      //生命周期方法。组建被移除时调用此方法
      componentWillUnmount () {
        BackAndroid.removeEventListener('hardwareBackPress', this.handleBack)   //增加手机物理返回键的监听
      }
    
    //双击返回键退出
    handleBack(){
        const { navigator } = this.props;
        if (navigator && navigator.getCurrentRoutes().length > 1) {
          navigator.pop();
          return true;
        }else{
          let timestamp = (new Date()).valueOf();
          if(timestamp - this.firstClick > 2000){
            MyToast.show('在按一次退出',MyToast.SHORT);
            this.firstClick = timestamp;
            return true;
          }else{
            return false;
          }
        }
      }
    
      //页面的跳转
      _pressButton(index){
        const { navigator } = this.props;
        if (navigator){
          switch (index) {
            case 2:
              navigator.push({
                name:'SecondPageComponent',
                component:SecondPageComponent,
              });
              break;
            case 3:
              navigator.push({
                name:'ThirdPageComponent',
                component:ThirdPageComponent,
              });
              break;
            case 4:
              navigator.push({
                name:'FourthPageComponent',
                component:FourthPageComponent,
              });
              break;
            default:
            break;
          }
        }
      }
    
      render(){
        return(
          <View>
            <TouchableOpacity onPress={this._pressButton.bind(this,2)}
                              style={{ flexDirection:'row', alignItems:'center' }}>
                <Text style={styles.red}>点我跳转到2
                </Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={this._pressButton.bind(this,3)}
                              style={{ flexDirection:'row', alignItems:'center' }}>
                <Text style={styles.red}>点我跳转到3
                </Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={this._pressButton.bind(this,4)}
                              style={{ flexDirection:'row', alignItems:'center' }}>
                <Text style={styles.red}>点我跳转到4
                </Text>
            </TouchableOpacity>
          </View>
        )
      }
    }
    
    const styles = StyleSheet.create({
      red:{
        fontSize:40,
        fontWeight:'300',
        color:'red'
      }
    });

    还是先从主要的方法说起

    return(
          <View>
            <TouchableOpacity onPress={this._pressButton.bind(this,2)}
                              style={{ flexDirection:'row', alignItems:'center' }}>
                <Text style={styles.red}>点我跳转到2
                </Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={this._pressButton.bind(this,3)}
                              style={{ flexDirection:'row', alignItems:'center' }}>
                <Text style={styles.red}>点我跳转到3
                </Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={this._pressButton.bind(this,4)}
                              style={{ flexDirection:'row', alignItems:'center' }}>
                <Text style={styles.red}>点我跳转到4
                </Text>
            </TouchableOpacity>
          </View>
        )

    这只是基本的排列,主要要解释是的是this._pressButton.bind(this,4)方法。这就是点击事件调用_pressButton(index)方法,index是this后面的参数,接下来看方法

    _pressButton(index){
        const { navigator } = this.props;
        if (navigator){
          switch (index) {
            case 2:
              navigator.push({
                name:'SecondPageComponent',
                component:SecondPageComponent,
              });
              break;
            case 3:
              navigator.push({
                name:'ThirdPageComponent',
                component:ThirdPageComponent,
              });
              break;
            case 4:
              navigator.push({
                name:'FourthPageComponent',
                component:FourthPageComponent,
              });
              break;
            default:
            break;
          }
        }
      }

    在这段代码中有一个难以理解的地方就是navigater对象是哪里来的?
    回到simplePageComponent.js中

    return < Component {…route.params} navigator={navigator} />

    在返回时返回了一个navigator对象的属性

    * const { navigator } = this.props; *
    这里就获取到了。

    navigator.push({
                name:'ThirdPageComponent',
                component:ThirdPageComponent,
              });

    这段代码就是将ThirdPageComponent组件放入navigator的栈中。达到显示的目的。
    ThirdPageComponent.js方法中就比较简单了

    import React, { Component } from 'react';
    import {
      View,
      StyleSheet,
      Navigator,
      Image,
      Dimensions,
      Text,
      TouchableOpacity
    } from 'react-native'
    
    var deviceWidth = Dimensions.get('window').width;
    
    const BANNER_IMGS = [
        require('../imgs/meinv2.png'),
        require('../imgs/meinv3.png'),
        require('../imgs/meinv4.png'),
        require('../imgs/meinv2.png')
    ];
    
    export default class ThirdPageComponent extends React.Component {
        constructor(props) {
            super(props);
            this._pressButton = this._pressButton.bind(this);
        }
    
        _pressButton() {
            //获取SampleComponent中创建的Navigator对象
            const { navigator } = this.props;
            //为什么这里可以取得 props.navigator?请看上文:
            //<Component {...route.params} navigator={navigator} />
            //这里传递了navigator作为props
            //这里对navigator进行了判断  如果navigator(导航器)对象存在的情况下 在进行操作
            if (navigator) {
                navigator.pop();
            }
        }
    
        _renderPage(data, pageID) {
            return (
                <Image
                    source={data}
                    style={styles.page}/>
            );
        }
    
        //创建点击区域 当点击的时候 进行 页面的跳转 也就是对navigator的参数进行设置  使其跳转到 第二个界面
        render() {
            return (
                <View >
                    <TouchableOpacity onPress={this._pressButton.bind(this)}
                                      style={{flexDirection:'row' ,alignItems: 'center'}}>
                        <Text style={styles.red}>点我跳回去</Text>
                    </TouchableOpacity>
                    <Text style={styles.red}>我是第三页面</Text>
                </View>
            );
        }
    }
    const styles=StyleSheet.create({
        red:{
            fontSize:40,
            fontWeight:'bold',
            color:'red'
    
        },
        container: {
            flex: 1,
            flexDirection: 'row',
            alignItems: 'flex-start',
            paddingTop:5,
            paddingLeft:5,
            backgroundColor:'#999999',
            paddingRight:5,
            paddingBottom:5,
        },
        page: {
            width: deviceWidth,//设备宽(只是一种实现,此处多余)
            flex: 1,
            height: 130,
            resizeMode: 'stretch'
        },
    });
    

    这个组件中只有一个重要代码

    navigator.pop();    //返回上一个组件

    恩!到此为止,一个react-native的原生的页面的跳转就完成,还加入一些返回的细节。(MyToast是桥接的android的Toast。实际使用的过程可以直接去掉,以免报错)

    展开全文
  •  由于工作原因,由Android原生开发转向React Native开发,ReactNative是从去年5月份开始至今,最近公司想要使用Android+H5开发,在这里,找了一篇文章,说一下Android 原生开发、H5、React-Native开发特点。...
  • 不知道何时开始, iconfont 成为了 App 开发的利器,不仅因为它是矢量图标,可以轻松... 而 react-native-vector-icons 是在 GitHub 上最火的 React Native 的 iconfont 图标库,也是这文章的主角。 react-native...
  • 第一次写主要是分享一下...很多人在RN端做微信分享的时候使用的是yorkie/react-native-wechat这个第三方库,这个库npm的最新版本没有小程序分享功能,下面就介绍两种解决方法。 1、在原来的react-native-wechat上...
  • 最近在忙着做rn移动端的开发,碰到不少问题,其中把微信支付的问题分享给大家,希望对大家有所帮助react-native 集成微信支付主要有两种方法(目前来说,不排除以后还有别的npm第三方包)第一种是使用npm包(react-native-...
  •  React-Native是一款由Facebook开发并开源的框架,主要卖点是使用JavaScript编写原生的移动应用。从2015年3月份开源到现在,已经差不多有半年。目前,React-Native正在以几乎每周一个版本的速度进行快速迭代,开源...
  • react-native 集成友盟推送 公司开发app时用到了,友盟推送,但是友盟的官方文档写的比较模糊;粗略整理一下从集成友盟推送,到打开推送消息的处理过程;如有处理不合适的地方欢迎指正!!!! 集成推送功能 友盟推...
  • 最近工作中接触到React-Native框架,对其进行一些技术分析,结合之前了解的H5的一部分,加上自己做了很久的原生开发(十几个android app、sdk,包括2个ios), 总结下目前了解到的这三种移动端应用开发方式的特点和...
  • 基于腾讯互动直播封装为React-Native,android、iOS都已封装。
  • https://www.tuicool.com/articles/vArUV3eReact-native-code-push 是微软针对React-native推出的热更新服务,最近的React-native...事实上 React-native-code-push 的 官方文档 写的十分详细,针对IOS和And...
  • 一.创建一个Swift工程,姑且为RNApp ...用于存放我们react-native的相关文件, 再创建一个package.json文件, 用于初始化react-native.(文件夹名字自定义哈) 文件目录结构如下: package.jsonw文件内容如下 其中na
  • 还是和微信支付一样,不使用任何的npm第三方包(react-native-yunpeng-alipay),使用rn+调用原生方法,所以要有一定的ios和android原生开发经验。参考http://fangzf.me/2017/12/05/react-native-集成支付宝/但是还有...
  • #react-native原生交互(Android) 1:在Android项目src包下面创建提供给react(以下简称rc)调用的类 package com.view; import android.widget.Toast; import com.facebook.react.bridge.ReactApplicationContext; ...
  • 背景:最近在学习React-Native相关的知识,有个需求,如果已经存在一个成熟的Android 或者 IOS项目,如何实现在后续的开发中用RN来实现部分功能。再此我只是讲解一下Android demo的两种实现方法。 一· 官方推荐...
  • (1)jpush-react-native 插件的集成与使用 Android 篇 https://www.jianshu.com/p/6721a0360af9https://github.com/qn9301/react-native-web-canvas(1)react native极光推送全程教程android和ios ...
  • react-native for android https证书认证react-native项目中,前端的请求其实都是调用原生插件发起的。 在android端,使用的是okHttp。 这篇博客是在react-native 0.47 + okhttp3 + tomcat的基础上讲解在本地生成自...
1 2 3 4 5 ... 20
收藏数 3,244
精华内容 1,297