React Native实现一个自定义模块

2018-02-05 15:59:11 浏览数 (1)

概述

在 前期介绍React Native 项目结构的时候,我们讲解过React的项目组成,其中说过 node_modules 文件夹,这是一个存放 node 模块的地方。我们知道React是用npm来管理项目的。提到npm,一般指两层含义:一是 Node.js 开放式模块登记和管理系统,另一种是 Node.js 默认的模块管理器,是一个命令行软件,用来安装和管理 node 模块。

npm 使用介绍

npm 是一个 Node.js 模块,安装 Node.js 会默认安装 npm,可以在终端中使用以下命令来查看 npm 的版本:

代码语言:javascript复制
npm -v

升级可以使用下面的命令

代码语言:javascript复制
sudo npm install npm -g

安装模块(安装完毕后会产生一个node_modules目录,其目录下就是安装的各个node模块)

代码语言:javascript复制
npm install <ModuleName>

其他的用法还请参考之前的博客:npm使用详解

今天我们要说的是用npm来创建一个我们自己的模块,就是Android的Libary

创建自定义模块

React Native 虽然实现了很多 Native 组件,并且提供了丰富的 API,但是有些原生库还是不支持的,而且有很多开源的组件和库是面向原生的,因此要想在 React Native 中使用这些组件和库就需要自己定义一个模块,这样也方便别人集成,我们还可以把它发到出去供别使用。

首先我们执行init创建一个项目:

代码语言:javascript复制
react-native init AwesomeProject

这里以 Android 为例,用 Android Studio 选择菜单 File->open 打开 AwesomeProject 文件夹下的 android 文件夹,然后选择 File -> New -> New Module,选择创建一个 Android Library,如图:

然后将所需要依赖的 jar 放到 libs 目录下,这里以使用 jpush-sdk 为例,将官网上下载的 libs 复制到 libs 下,把相关的资源文件放到 res 文件夹下,再把 AndroidManifest 文件内容复制过来,更改一下包名,最后在 build.gradle 中配置一下。

代码语言:javascript复制
apply plugin: 'com.android.library'
android {    
  compileSdkVersion 23    
  buildToolsVersion "23.0.2"    
  defaultConfig {        
    minSdkVersion 16        
    targetSdkVersion 22        
    versionCode 1        
    versionName "1.0"        
    manifestPlaceholders = [                
      JPUSH_APPKEY: "yourAppKey",  //在此修改JPush的AppKey                    
      APP_CHANNEL: "developer-default"      //应用渠道号        
    ]    
  }    
  lintOptions {        
    abortOnError false        
    warning 'InvalidPackage'    
  }    
  sourceSets {        
    main {            
      jniLibs.srcDirs = ['libs']        
    }    
}
}
repositories {    
  mavenCentral()
}

dependencies {    
  compile fileTree(dir: 'libs', include: ['*.jar'])    
  compile "com.facebook.react:react-native: "
}

接下来需要写 Native 和 JS 交互的代码,这个可以参考之前的关于原生和js交互的文章点击打开链接。假设我们已经完成了 Native 部分代码,我们如何才能在 JS 中让他人能够通过 import 的方式调用我们的 JS 代码,从而调用 Native 呢?首先进入 my-react-library 文件夹,然后在终端执行:

代码语言:javascript复制
npm init

生成 package.json 文件(注意这里的 name 字段,这里是别人引用你的模块的名字),然后再创建一个 index.js 文件,这是 node 模块的 JS 入口。例如我引用了jpush

代码语言:javascript复制
import {NativeModules, Platform, DeviceEventEmitter} from 'react-native';

// 通过 NativeModules 找到我们在 Native 定义的 JPushModule 类
const JPushModule = NativeModules.JPushModule;

export default class JPush {

    /**
     * Android only
     * 初始化JPush 必须先初始化才能执行其他操作
    */
    static initPush() {
        JPushModule.initPush();
    }
}

发布自定义模块

到此为止,我们已经完成了 React Native 自定义模块。现在可以发布我们的自定义模块了。在 package.json 所在的目录下执行:

代码语言:javascript复制
npm publish

这样就可以把我们的自定义模块上传到 npm 库了,每次更新版本时,需要改动 package.json 中的 version 值,然后再执行 npm publish 即可。

保存自定义模块

安装完成后就会把这个模块保存到 node_modules 文件夹下,由于我们的模块是一个 Android Library 项目,所以在 Native 中还需要配置一下。我们使用如下命令保存自己的模块。

代码语言:javascript复制
npm install my-react-library --save

someone's react-native project/some module/build.gradle

这里主要是添加项目依赖

代码语言:javascript复制
dependencies {    
  compile fileTree(dir: "libs", include: ["*.jar"])    
  compile "com.android.support:appcompat-v7:23.0.1"    
  compile "com.facebook.react:react-native: "  // From node_modules   
  // 在 dependecies 中加入自定义模块 
  compile project(':my-react-library')
}

然后在 settings.gradle 中也要配置一下(这个搞过Android就很熟悉)

代码语言:javascript复制
include ':app', ':my-react-library'
project(':my-react-library').projectDir = new File(rootProject.projectDir, '../node_modules/my-react-library/android')

在 MainActivity 中将自定义的 Package 添加进去(因为启动时在这里触发的)

代码语言:javascript复制
mReactInstanceManager = ReactInstanceManager.builder()                
.setApplication(getApplication())                
.setBundleAssetName("index.android.bundle")                
.setJSMainModuleName("react-native-android/index.android")                
.addPackage(new MainReactPackage())
//添加自定义的 package
.addPackage(new MyReactPackage())

如果是 RN 0.29.0 以上版本,则还应在 MainApplication 中添加

代码语言:javascript复制
@Overrideprotected List<ReactPackage> getPackages() {    
return Arrays.<ReactPackage>asList(            
    new MainReactPackage(),            
    new MyReactPackage()    
  );
}

到此为止我们完成了 Native 部分的配置(完成后 sync 一下),接下来就可以使用了。

代码语言:javascript复制
export default class SomeClass  extends React.Component {
    componentDidMount() {
      // 调用 index.js 中定义的 doSomething()
      MyModule.doSomething();
    }
}

0 人点赞