如何在React Native中寫(xiě)一個(gè)自定義模塊
前言
在 React Native 項(xiàng)目中可以看到 node_modules 文件夾,這是存放 node 模塊的地方,Node.js 的包管理器 npm 是全球***的開(kāi)源庫(kù)生態(tài)系統(tǒng)。提到npm,一般指兩層含義:一是 Node.js 開(kāi)放式模塊登記和管理系統(tǒng),另一種是 Node.js 默認(rèn)的模塊管理器,是一個(gè)命令行軟件,用來(lái)安裝和管理 node 模塊。本文旨在探討如何在 React Native 中寫(xiě)一個(gè)自定義的 npm 模塊(類(lèi)似于插件),并上傳到 npm 上供他人使用。
npm 使用介紹
npm 是一個(gè) Node.js 模塊,安裝 Node.js 會(huì)默認(rèn)安裝 npm,可以在終端中使用以下命令來(lái)查看 npm 的版本:
- npm -v
升級(jí) npm:
- sudo npm install npm -g
安裝模塊(安裝完畢后會(huì)產(chǎn)生一個(gè)node_modules目錄,其目錄下就是安裝的各個(gè)node模塊):
- npm install <ModuleName>
查看 npm 配置:
- npm config list
設(shè)置代理:
- //設(shè)置 http 代理
- npm config set proxy http://server:port
- //設(shè)置 https 代理
- npm config set https-proxy http://server:port
上面介紹了一些 npm 基本命令,接下來(lái)就可以在本地創(chuàng)建一個(gè)模塊啦。 首先打開(kāi)終端中新建一個(gè)你想在此創(chuàng)建自定義模塊的文件夾,然后在命令行中登錄 npm。輸入以下命令:
- npm adduser
接下來(lái)會(huì)提示你輸入用戶(hù)名和密碼還有郵箱,一一完成后就可以輸入以下命令來(lái)查看當(dāng)前 npm 用戶(hù)了:
- npm whoami
如果正確顯示了剛才注冊(cè)的用戶(hù)名,說(shuō)明登錄成功了。然后就使用以下命令來(lái)創(chuàng)建 npm 模塊:
- npm init
執(zhí)行上述命令后,會(huì)引導(dǎo)你創(chuàng)建一個(gè)package.json文件,包括名稱(chēng)、版本、作者這些信息等。
創(chuàng)建模塊
這里要提一下,為什么要寫(xiě)一個(gè)自定義模塊。因?yàn)?React Native 雖然實(shí)現(xiàn)了很多 Native 組件,并且提供了豐富的 API,但是有些原生庫(kù)還是不支持的,而且有很多開(kāi)源的組件和庫(kù)是面向原生的,因此要想在 React Native 中使用這些組件和庫(kù)就需要自己定義一個(gè)模塊,這樣也方便別人集成。接下來(lái)我們直接進(jìn)入正題。寫(xiě)一個(gè) React Native 中可以使用的自定義模塊。在命令行中執(zhí)行
- react-native init AwesomeProject
初始化一個(gè) React Native 項(xiàng)目。這里以 Android 為例,用 Android Studio 選擇菜單 File->open 打開(kāi) AwesomeProject 文件夾下的 android 文件夾,然后選擇 File -> New -> New Module,選擇創(chuàng)建一個(gè) Android Library,如圖:
然后將所需要依賴(lài)的 jar 放到 libs 目錄下,這里以使用 jpush-sdk 為例,將官網(wǎng)上下載的 libs 復(fù)制到 libs 下,把相關(guān)的資源文件放到 res 文件夾下,再把 AndroidManifest 文件內(nèi)容復(fù)制過(guò)來(lái),更改一下包名,***在 build.gradle 中配置一把,如下(這里要注意把 targetSdkVersion 改成 22,在23上運(yùn)行可能會(huì)閃退):
- 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" //應(yīng)用渠道號(hào)
- ]
- }
- 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:+"
- }
到此為止,我們已經(jīng)完成了***步操作,接下來(lái)需要寫(xiě) Native 和 JS 交互的代碼,可以參考我的這篇文章中 JS 調(diào)用 Native 以及 Native 調(diào)用 JS 部分,這里不再贅述。假設(shè)我們已經(jīng)完成了 Native 部分代碼,我們?nèi)绾尾拍茉?JS 中讓他人能夠通過(guò) import 的方式調(diào)用我們的 JS 代碼,從而調(diào)用 Native 呢?首先進(jìn)入 my-react-library 文件夾,然后在終端執(zhí)行
- npm init
生成 package.json 文件(注意這里的 name 字段,這里是別人引用你的模塊的名字),然后再創(chuàng)建一個(gè) index.js 文件,這是 node 模塊的 JS 入口,這里推薦使用 Sublime Text 進(jìn)行 JS 的編寫(xiě)。這里以 jpush-react-native 為例:
jpush-react-native/index.js 部分代碼
- import {NativeModules, Platform, DeviceEventEmitter} from 'react-native';
- // 通過(guò) NativeModules 找到我們?cè)?nbsp;Native 定義的 JPushModule 類(lèi)
- const JPushModule = NativeModules.JPushModule;
- export default class JPush {
- /**
- * Android only
- * 初始化JPush 必須先初始化才能執(zhí)行其他操作
- */
- static initPush() {
- JPushModule.initPush();
- }
- }
上面定義了一個(gè) initPush 方法,initPush 實(shí)際上調(diào)用了 JPushModule 中定義的 initPush 方法,其他方法與此類(lèi)似,本質(zhì)上都是通過(guò) NativeModules 調(diào)用了 Native 提供的方法。
發(fā)布
到此為止,我們已經(jīng)完成了 React Native 自定義模塊?,F(xiàn)在可以發(fā)布我們的自定義模塊了。在 package.json 所在的目錄下執(zhí)行
- npm publish
就可以把我們的自定義模塊上傳到 npm 庫(kù)了。每次更新版本時(shí),需要改動(dòng) package.json 中的 version 值,然后再執(zhí)行 npm publish 即可。
使用
在 React Native 目錄下,執(zhí)行:
- npm install my-react-library --save
安裝完成后就會(huì)把這個(gè)模塊保存到 node_modules 文件夾下,由于我們的模塊是一個(gè) Android Library 項(xiàng)目,所以在 Native 中還需要配置一下。主要是添加項(xiàng)目依賴(lài):
someone's react-native project/some module/build.gradle
- 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 中也要配置一下:
someone's react-native project/settings.gradle
- include ':app', ':my-react-library'
- project(':my-react-library').projectDir = new File(rootProject.projectDir, '../node_modules/my-react-library/android')
在 MainActivity 中將自定義的 Package 添加進(jìn)去:
MainActivity.java
- ...
- 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 以上版本,則應(yīng)在 MainApplication 中添加:
MainApplication.java
- @Overrideprotected List<ReactPackage> getPackages() {
- return Arrays.<ReactPackage>asList(
- new MainReactPackage(),
- new MyReactPackage()
- );
- }
到此為止我們完成了 Native 部分的配置(完成后 sync 一下),接下來(lái)就可以使用了。 別人要使用我們的模塊時(shí),就可以這樣寫(xiě):
someone.js
- //這里的 'my-react-library'是在 package.json 定義的 name
- // 這樣就可以
- import MyModule from 'my-react-library'
- export default class SomeClass extends React.Component {
- componentDidMount() {
- // 調(diào)用 index.js 中定義的 doSomething()
- MyModule.doSomething();
- }
- }