构建
-
RN编译不监听修改是代码有错
-
RN编译后的代码文件位于
project/rn_temp/
下(RN编译后的源码可作参考)。 -
小程序编译后的代码文件位于
project/dist/weapp/
下。 -
进行RN的编译时,确保
React Native Debugger.exe
程序在运行,用于传输js数据。不开启则代码改动不会生效。 -
编译小程序:
npm run dev:weapp
重新编译小程序后,Taro不会编译sitemap文件,微信开发工具会报找不到sitemap文件的错误,需要手动将src文件夹内的sitemap放入dist小程序编译根目录中。 -
编译RN:
npm run dev:rn
,编译完成后会开启一个node命令行窗口,通过8081端口用于传输JS代码,此时应该确保React Native Debugger.exe
程序在运行。 -
打包RN(debug):
flush-android-debug.bat
或react-native run-andorid
或npx react-native run-android
-
打包RN(release):
flush-android-release.bat
或react-native run-andorid --variant=release
或npx react-native run-android --variant=release
需要卸载原模拟器里的debug版本,否则自动安装不上,或者可以去project/android/app/build/outputs/apk/release/
目录里拿出APK手动拖到模拟器窗口里或者放到真机上安装。 -
打包debug版的APK安装后,进行调试前需要按下
Ctrl+M
,点击Debug JS Remotely
开启远程JS调试,用于接收React Native Debugger.exe
传输过来的,编译后的JS代码。不开启则代码改动不会生效。 -
确保以上操作都正确,如果还是没更新代码或者连接
React Native Debugger.exe
的话,去开启模拟器的WIFI。 -
打包本地图片,新增本地图片时或者初次打包release时需要(确保assets目录存在,不存在则新建文件夹,敲命令前先编译RN):
react-native bundle --platform android --dev false --entry-file rn_temp/index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
运行完毕后需要进入
android/app/src/main/res/
目录内删除svg格式图片,否则APK打包报错 -
使用他人的node_modules包(尤其是不同系统平台的),在使用npm命令前可能需要重置node-sass包:
npm rebuild node-sass
以上命令都在项目根目录运行
- iOS Debug 构建需要另外在
project/ios/
目录下安装pod install
(每次插件更新都要运行pod install
)
pod install
报插件红字错误的话,删除Podfile.lock
文件后再重试
-
iOS Debug 构建流程:
npm run dev:rn
- 在Xcode中导入
project/ios/
编译后的ios项目目录 - 在Xcode左上角菜单栏
preference -> accounts -> 添加Apple ID开发账号 -> 主界面选择模拟器 -> 构建运行
-
iOS app内呼出开发控制菜单:
command + control + Z
,或者顶部菜单栏:设备(Device)-> 摇一摇(Shake)
-
iOS 构建成功后无法在模拟器中启动APP:检查Xcode设置中开发者账号是否需要重新登录验证。
-
iOS
pod install
构建错误:CocoaPods could not find compatible versions for pod "Folly": In snapshot (Podfile.lock):
删除
project/ios/Podfile.lock
文件后重新运行pod install
-
iOS真机调试:将手机连接电脑,配置打包签名为Automatically,Team选择个人开发者账户,Bundle Identifier会联网检查,如果不处在同一Team下进行开发,则需要修改为不重复的包名。运行终端模拟器选择刚才连接的手机,点击运行将自动安装到手机上,第一次安装后需要到设置中开启信任模式,否则iOS将禁止调试app运行。运行后的app摇一摇可以呼出控制菜单,如果想要连上
React Native Debugger.exe
,需要开启Debug JS Remotely
,并通过WiFi连接到和电脑的同一局域网,并设置连接地址IP等操作。
参考连接
- Xcode构建崩溃:顶部菜单栏->Product->Clean Build Folder 清空构建缓存
代码
-
this.setState()
是异步执行的,可以通过回调参数来保证已经set完毕:this.setState({ a: 'a' }, () => { console.log(this.state.a) })
-
Taro判断小程序平台和RN平台表达式:
process.env.TARO_ENV === 'rn' process.env.TARO_ENV === 'weapp'
-
RN判断Android平台和iOS平台表达式(需导包):
import {Platform} from 'react-native' ... Platform.OS === 'android' Platform.OS === 'ios'
-
只有页面才有
componentDidShow
生命周期方法,组件是没有的。可以在页面里的componentDidShow
方法中,通过持有组件引用来调用组件内方法,来达到componentDidShow
的效果。 -
Taro中的props的值是不能改变的需要转换成state来改变:
static defaultProps = { show: false } state = { sShow: false } constructor(props) { super(props); this.state.sShow = props.show; } ...
-
Taro中的
e.stopPropagation();
冒泡处理在RN不适用需要加上判断 -
JS在遍历中的同时删除数组元素:解决办法
标签
-
任何标签都是大写字母开头,否则RN报红屏错误。
-
所有文本都需要使用
<Text></Text>
标签包裹,否则RN红屏闪退,且color
、font-size
等文本属性只针对<Text>
标签生效。 -
RN限制文本行数:
<Text numberOfLines={1} />
-
给组件设置引用,可以通过引用调用组件内部方法:
this.Modal && this.Modal.show() ... <Modal ref={(c) => this.Modal = c}>
调用前需要判断组件是否已经渲染完毕,否则会报undefined
-
当导入的RN组件与Taro组件重名时,可以起一个别名一起使用:
import {Image} from '@tarojs/components' import {Image as RnImage} from 'react-native'
-
视图渲染中所用用到RN相关组件的地方都需要加平台判断,组件引用时也需要加平台判断,否则小程序编译会报
缺少npm包AccessibilityInfo,开始安装...
:(import
则会在编译时自动忽略不属于当前平台的组件)import {Image as RnImage} from 'react-native' ... componentDidMount = () => { if (process.env.TARO_ENV === 'rn') { this.RnImage.getSize() } } ... {process.env.TARO_ENV === 'rn' && ( <Block> <RnImage ref={(c) => this.RnImage = c} source={{uri: data}} /> </Block> )}
-
点击事件等事件传递,需要使用
bind()
方法:onClickItem = (a, b, c, event) => { ... } ... <View onClick={this.onClickItem.bind(this, a, b, c)} />
onClick
中的this
参数一定要写在首位,后面按照方法参数顺序排列。方法中的event
对应标签中的this
,用来传递事件对象,要放在末尾。不再使用小程序的data-*
方式传参 -
不能在
<Image></Image>
标签内写子布局,且<Image />
标签无法直接设置点击事件,需要使用<View></View>
标签包裹起来,然后给<View />
标签点击事件。 -
当
<View />
标签只包裹<Image />
时,需要给定和<Image />
标签一样的宽高值,否则会导致弹性布局的垂直居中属性无效。 -
当
( )
中只有一个组件标签时,需要使用<Block></Block>
将标签包裹起来,否则会有语法错误,需要导包:import {Block, Image} from '@tarojs/components' ... {isShow && ( <Block> <Image /> </Block> )}
-
Taro自带的
<Image />
组件在RN里会有圆角问题,必要时可使用RN的<Image />
组件:import {Block, Image} from '@tarojs/components' import {Image as RnImage} from 'react-native' ... {process.env.TARO_ENV != 'rn' ? ( <Block> <Image className="img" src={'https://avatar.png'} /> </Block> ) : ( <Block> <RnImage className="img" source={{uri: 'https://avatar.png'}} /> </Block> )} ... .img { width: 100px; height: 100px; border-radius: 100px; }
RN的组件在用法上完全和RN原生用法一致
-
在RN上使用Taro的
<Image />
组件时,必须设置固定宽高,否则第一次进入APP时将不会显示,且不能带有mode
属性。 -
iOS文本下划线颜色设置:
<Text style={{textDecorationColor: "white"}} className="integral-rule-txt">文本</Text>
样式
-
优先使用flex布局
-
行内样式必须加
{ }
包裹,否则不生效(RN需要{{ }}
):<View style={'height: 100rpx'}>
-
Taro只会对写在CSS文件里的px单位自动做缩放,不会对行内样式中的px单位自动做缩放。
-
在行内样式中,小程序平台需要使用rpx来保证小程序各尺寸缩放,RN平台则不需要写单位(RN行内样式单位默认为点
(point)
),小程序的rpx和RN的点(point)
比例为2倍,css文件中的px是行内样式中点(point)
的2倍:<View style={process.env.TARO_ENV === 'rn' ? {height: 100} : 'height: 200rpx;' }>
-
很多CSS样式在RN上不支持,有些可能会导致闪退,在CSS上做平台判断:
/* #ifdef rn */ ... /* #endif */ ... /* #ifndef rn */ ... /* #endif */
-
RN
position
样式只支持relative
和absolute
,不支持block
、fixed
等(会闪退)。 -
border-radius
不支持百分比。圆头像图片框圆角值需要设置成宽高值的一半,过大或过小都会在ios上导致变形。 -
display: flex;
小程序默认方向为水平,RN默认方向为竖直。 -
iOS中
border-bottom
样式失效修复:不能直接在<Text>
上加border-bottom
样式,需要在外面套一层<View>
,给<View>
加border-bottom
。border-radius
同理,<Text>
只适用文本相关样式,文本无关样式需要给<View>
加上并包裹<Text>
达到效果。 -
text-align: center;
不生效:1.检查样式是否已设置在<Text>
标签上。2.检查<Text>
是否有宽度。3.检查<Text>
的父组件是否已设置display: flex;
插件
-
安装流程
下载插件: npm install <插件名>@<版本号> --save 示例:npm install react-native-image-crop-picker@0.23.1 --save React Native 0.60.x之前的版本需要手动link, 链接到RN项目:react-native link <插件名> 示例:react-native link react-native-image-crop-picker iOS端则需要进入/ios目录中运行一遍命令:pod install
以上命令都在项目根目录运行
-
提示
-
有一些RN插件会使用androidX包导入,比如react-native-view-shot插件,因为RN现在版本较低需要修改导入包路径为android.support.xxx,具体路径需要根据包名而定。
-
选择插件时在Readme中,注意插件有没有对RN版本有要求,根据RN版本下载,最好选择都支持IOS/Android
react-native react-native-image-resizer ≤ 0.60 1.1.0 0.61 1.2.0
-
-
react-native-image-crop-picker
react-native-image-crop-picker是一款注重剪裁,相册单选、多选的第三方框架。
-
react-native-image-resizer
图片压缩插件
- github : react-native-image-resizer
- 相关链接: https://translate.google.cn/
-
react-native-view-shot
截图插件
-
react-native-smart-barcode
app扫描二维码插件
-
github: react-native-smart-barcode
-
插件使用的二维码库:ZXing
-
获取图片本地路径识别二维码:
i. 调用的android目录下的RCTCaptureModule.java中DecodeFromPath() 方法
图片路径为:
path: "/data/user/0/com.package.project/cache/1594624681380.JPEG"
ii. DecodeUtil.java
图片转换为Bitmap格式,原插件会在转换为YUV格式,提高二维码识别速度。但是getYUV420sp()在转换中抛出异常,找不到错误位置,判断是数组越界。换为直接使用Bitmap格式。
-
-
CameraRoll
RN原生组件,CameraRoll
模块提供了访问/保存本地相册的功能。 -
Android获取权限,Android6.0以上的设备需要动态申请权限。
-
react-native-webview
低版本RN自带的WebView插件,高版本已分离,需要手动npm install。
已针对ios进行修改:react-native-webview的ios端实现禁止在注入js内使用window.postMessage()
方法,所以在project/node_modules/react-native/React/Views/RCTWebView.m
中进行了修改:BOOL postMessageIsNative = [ [webView stringByEvaluatingJavaScriptFromString:testPostMessageNative] isEqualToString:@"true" ]; // package-edit:解除webview内嵌js中window.postMessage //if (!postMessageIsNative) { // RCTLogError(@"Setting onMessage on a WebView overrides existing values of window.postMessage, but a previous value was defined"); //} // package-edit:解除webview内嵌js中window.postMessage #endif
ReactNative-iOS原生代码二次修改
-
修复ios输入法遮挡问题:参考链接
-
Xcode11以上编译报错:Unknown argument type ‘attribute’ in method -[RCTAppState getCurrentAppState:error:]. Extend RCTConvert to support this type.
//project/node_modules/react-native/React/Base/RCTModuleMethod.mm static BOOL RCTParseUnused(const char **input) { return RCTReadString(input, "__unused") || // package-edit:Xcode11以上编译报错修复 RCTReadString(input, "__attribute__((__unused__))") || // package-edit:Xcode11以上编译报错修复 RCTReadString(input, "__attribute__((unused))"); }
-
修复ios中文输入法(已在0.57node包中修改,搜索注释package-edit可找到):参考链接
// package-edit:修复中文输入法 RN 0.57版本 if (_onChange && backedTextInputView.markedTextRange == nil) { _onChange(@{ @"text": self.attributedText.string, @"target": self.reactTag, @"eventCount": @(_nativeEventCount), }); }