1、ios 不支持汉字斜体问题
react-native fontStyle:italic 只针对英文生效
解决方案:
//为Text 添加2d变换实现倾斜
{transform: [{ skewX: '-15deg' }],}
2、针对ui设计的大小建议只做参考,大多数时候,他们会要求不区分屏幕尺寸呈现相同的效果。
解决方案: 设计按钮大小排布间距的时候使用
const {width} = Dimensions.get('window')
使用这个宽度 - 间隔 ➗ 排布数量是最合适的解决方案(注:少走弯路~)
虽然在pad或类似超大尺寸设备上会和难看~
3、子组件通信 子-》父-》子 太过冗杂
解决方案: NativeEventEmitter原生事件很好用。 react-native 提供的原生事件。并不推荐所有的数据传递或者事件监听触发都使用这个,这会让代码看起来一团糟。
但是同一页面的兄弟通信切不涉及数据传递,还是推荐使用
import {NativeEventEmitter} form 'react-native'
//child1.tsx
NativeEventEmitter.emit(xxx,{})
//child2.tsx
NativeEventEmitter.addListener(xxx,()=>any)
4、弹窗冲突问题
解决方案: 统一塞到队列里,先进先出。有排序需求就先排序再出
5、在textInput 限制最大长度的情况下,复制一段长文本的值进去长文本会被切割,且无法得到具体的值
解决方案:查了一下,没有找到解决方案,只有放开最大长度的限制。并通过js限制
6、两个 textInput 的onfocus 切换,不需要调用onblur()事件,调用后会造成页面的闪动现象。
解决方案:
//直接
ref.current.onFocus()
7、 ;在Text 显示不会空格
解决方案:添加\xa0\xa0\xa0\xa0\xa0\xa0
实测➕6个大概是空两格的效果
8、替换git 登录信息错误
使用mac 安装完xcode,一般xcode会写入git配置
credential.helper=osxkeychain
解决方案: 验证信息会默认存在钥匙链上,重新登陆git需要在钥匙链上删除对应git缓存
9、Dimensions 的宽度测量不正确,从横屏页面跳转过来
解决方案:如果需要在组件内部实时获取到当前window的width。需要使用正确的方法
function A (){
// ok
const {width} = useWindowDimensions()
//error
const {width} = Dimension.get('window')
}
10、图片在实时设置了宽高时,在宽高变化时,图片未正常渲染,呈现了被截取一部分的状态
解决方案:需要在修改 属性 resizeMode: contain
11、调用navigation.goBack()的行为和左上角按钮的返回的行为并不是一致的,需要注意
调用navigation.goBack()。beforremove 监听到的事件类型是'GP_BACK',而右上角点击后触发的事件类型为‘POP'。所以处理返回监听的时候需要记住这一点
12、在ios手机更新到最新的系统后,使用xcode打包提升不支持设备
解决方案:更新xcode到最新版,但是有时候因为mac系统没更新,所以没有办法更新xcode。可以使用以下方法 github.com/filsv/iPhon…
下载需要的ios版本支持,将下载的支持文件放入以下目录,可以启用支持
open /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/
13、安卓打包失败提示compileSdkVersion 错误,或者其他编译错误
检查 android/build.gradle 配置
buildToolsVersion = "30.0.2"
minSdkVersion = 21
compileSdkVersion = 30
targetSdkVersion = 30
ndkVersion = "21.4.7075529"
打开android studio 检查编译选项的配置是否满足配置寻求
14、禁止安卓暗黑模式
解决方案:
//android/app/src/main/res/values/styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:forceDarkAllowed">false</item>
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
</style>
注意一定要添加android:forceDarkAllowed false
15、禁用手势未正确关闭。
如果发现手势被禁用,那么大概率是关闭手势事件忘了移除,或者错误移除。不是什么玄幻事件
16、引入字体自定义字体时,ios显示字体android不显示 或者出现相反情况。
解决方案: android 和ios引入字体名称时引入规则不同。android 自己引入字体命名就可以,ios需要引入字体打开后显示的名字。所以需要区别应用
fontFamily:
Platform.OS === 'android'
? 'Roadgeek 2005 Engschrift Regular'
: 'Roadgeek 2005 Engschrift',
17、TextInput placeholder熟悉,需要实现占位符的换行
解决方案:
placeholder={`1、上午十点和同事开会,讨论进去规划;${'\n'}2、中午和朋友去吃创意菜,要记得带给他的礼物。${'\n'}3、下午三点要去提交材料;${`\n`}4、晚上约了宠物医院,要带小猫去体检,记得带上疫苗本`}
只有这样才能生效
18、ahooks useInterval 返回值clear()回调崩溃
解决方案: 需要将ahooks版本升级到3.0,老版本的useInterval没有clear ,然而浏览ahook的文档一般都是最新的文档,需要注意这个差异
yarn upgrade ahook
19、 安装lottie-ios@3.4.0 依赖时报错报错
执行pod intsall时会报错,错误信息为
cocospod不能找到可兼容的lottie-ios的版本
这是插件的问题,目前作者还没解决。可能下个版本还未修复。
解决办法有两个
1、降低lottie-ios的版本为3.2.3 问题暂时得到解决
2、 修改node_modules/lottie-react-native/lottie-react-native.podspec
//del
s.dependency 'lottie-ios', '~> 3.2.3'
//add
s.dependency 'lottie-ios', '~> 3.4.0'
以上两个办法能解决这个问题,第二个方法请配个patch-package 使用
20、动画无法播放
ui 基于AE lottie导出的插件可能是无法使用,或者兼容性存在问题的。检查方法为将导出的json文件上传到
这个网站上测试一下,看下是否正常、避免反复折腾。
21、测量静态图片大小
解决方案:Image 提供了一个静态方法可以测量图片的原始值,可以利用这一点来获取原始宽高
Image.resolveAssetSource(source);
22、弹窗的输入框被弹出的键盘挡住
这种情况keyboardAvoidScrollView 解决不了,最后决定手动加个动画,去移动弹窗的位置,当输入OnFocus时,触发动画,抬升弹窗、onBlur 时移除动画,复原位置
import Animated, {
Easing,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';
const animatedStyles = useAnimatedStyle(() => ({
top: withTiming(offset.value, {
duration: 500,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
}),
}));
const offset = useSharedValue(0);
//template
<TextInput
onFocus={() => {
offset.value = Platform.OS === 'ios' ? -100 : 0;
}}
onBlur={() => {
offset.value = 0;
}}
/>
23、重复高速点击按钮的防抖和节流整么处理
长期困扰开发的一个问题,使用正常的防抖节流处理避免不了快速点击出现的问题,在触发动作前还是会有一些点击空间。会触发一些恶性bug导致崩溃
解决方案: 经过一翻探讨、最后决定使用双重保险来解决这个问题,任何涉及到跳转或者访问借口的方法都需要添加两个东西 useLockFn 和主动 sleep
useLockFn 来自ahook,在 submit 函数执行完成前,其余的点击动作都会被忽略。
sleep 为中断线程
useLockFn(()=>{
xxx
sleep()
})
在两者的共同作用下,彻底解决了防抖
24、在页面focus时需要调用函数,在页面unFocus时也需要调用函数
在开发过程中遇到需要有这种需求的地方越来越多。于是我们新增了一个通用的Hook useFocusChangeEffect
function useFocusChangeEffect(
focusCallback: () => void,
depend: any[],
blurCallback?: () => void,
) {
const isFocused = useIsFocused();
useEffect(() => {
let callback;
if (isFocused) {
callback = focusCallback();
} else if (blurCallback) {
blurCallback();
}
if (typeof callback === 'function') {
return callback;
}
return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isFocused, ...depend]);
}
使用方法和useEffect 一致,区别是第一个参数函数会在onfocus 的调用,第三个参数函数会在onBlur时调用。此hook成为使用最高的hook
25、返回时依据来时路由跳转到目标位置
返回路由时需要根据实际历史路由判断返回到哪里,当有这种需求时,就需要获取历史记录 核心时监听路由变化,当返回时获取routes = navigation.getState(),然后通过记录判断
import {
NavigationProp,
RouteProp,
StackActions,
useNavigation,
useRoute,
} from '@react-navigation/native';
const backFunc = useCallback(
(e: any) => {
e.preventDefault();
if (e.data.action.type === 'GO_BACK') {
const { routes } = navigation.getState();
navigation.removeListener('beforeRemove', backFunc);
if (
routes[routes.length - 2].name === 'xxx'
const popAction = StackActions.pop(3);
navigation.dispatch(popAction);
} else navigation.dispatch(e.data.action);
} else {
navigation.dispatch(e.data.action);
}
},
[navigation],
);
useFocusChangeEffect(
() => {
navigation.addListener('beforeRemove', backFunc);
return () => navigation.removeListener('beforeRemove', backFunc);
},
[],
() => {
navigation.removeListener('beforeRemove', backFunc);
},
);
26、转化屏幕显示方向的同时退出当前页面,会引起页面卡死在转化的页面
解决方案,在调用navigation.goBack()时,需等待方向转化执行完毕,即需要手动加一点延迟。
Orientation.lockToPortrait();
setTimeout(() => {
navigation.goBack();
}, 400);
这样就不会引起卡死
27、静态页面添加微信的适配
微信浏览器无法直接下载安装包,需要用户使用其他浏览器打开,所以需要这么一个提示。
var isWx = u.toLowerCase().match(/MicroMessenger/i) == "micromessenger";
var isWxWork = u.toLowerCase().match(/WxWork/i) == "wxwork";
if (isWx || isWxWork) {
modal.style.display = "block";
}
<div class="modal" style="display:none">
<div class="content">
<img src="./img/arrow.png" class="arrowImg" />
<div class="hint">
点击右上角<img src="./img/more.png" class="moreImg" alt="" />打开菜单
</div>
<div class="hint">
选择<img
src="./img/browser.png"
class="browserImg"
alt=""
/>用浏览器打开下载
</div>
</div>
</div>
28、图表的纵轴标识为图片的情况
因为chart 需要跑在WebView中,所以想要纵轴是图片就需要将图片转化成二进制形式,放入图表config中。
解决方案:是将原本值转化为匹配规则,通过富文本自定义显示,为匹配到的规则添加背景图,以此来完成图片的显示
yAxis: {
type: 'category',
data: ['4', '3', '5', '6', '1', '7', '0', '2'],
axisLine: {
show: false,
},
splitLine: {
show: true,
},
axisTick: {
show: false,
},
axisLabel: {
formatter: (value: string) => {
'show source';
const rule: Record<string, string> = {
'0': 'happy',
'1': 'calm',
'2': 'rod',
'3': 'angry',
'4': 'cry',
'5': 'worry',
'6': 'speechless',
'7': 'leisure',
};
return `{${rule[value]}|}`;
},
margin: 20,
rich: {
happy: {
fontSize: 24,
backgroundColor: {
image: happy,
},
},
calm: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: calm,
},
},
rod: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: rod,
},
},
angry: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: angry,
},
},
cry: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: cry,
},
},
worry: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: worry,
},
},
speechless: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: speechless,
},
},
leisure: {
fontSize: 24,
align: 'center',
backgroundColor: {
image: leisure,
},
},
},
},
},
29、手机号匹配限制的太死导致上线出现问题
手机号登陆时的限制应该放松一点,只需要校验9个数字就好
(!/^1[123456789]\d{9}$/.test(phone))
30、TextInput ios和安卓存在差异化
TextInput 在不同平台上的样式不相同,主要体现在padding上。所以使用TextInput组件时,先将padding设置为0。抹平差异
31、安卓打包时出现OutOfMemoryError
如果打包的文件很多,会出现OutOfMemoryError,导致问题出现的原因是react-native后台进程默认分配的内存不够 安卓打包依赖于jvm,查看/android/gradle.properties 文件
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
将jvm参数修改一下就能解决问题,成功打包
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
32、使用安卓真机开启debug调试时,有时会出现不能跳页,点击不动的情况
这种情况如果启用toggle inspector,查看点击元素就会发现实际上是没有点击事件。导致问题的原因是因为安卓手机时间与mac时间不一致。调用adb命令,可以看到如果误差在一秒以上,就会出现此问题。 解决问题的方法就是是时间一致。我的解决方案为关闭mac和安卓的同步网络时间。并手动更改时间。就能解决问题
33、两个modal 同时渲染会出现页面卡死,无法点击的问题
这个问题非常常见,其涵盖的范围为react-native的modal组件和Toast,很多bug都是这问题导致的。其会导致以下问题
- 不能在modal里面弹出modal,会卡死
- 不能同时打开两个modal
- 关闭前一个modal时打开下一个需要使用setTimeout()做异步,来避免上一个modal未完全关闭就打开下一个
- 其他类似问题 解决方案,为避免同时出现两个modal,或者用View来做弹窗最好的自己写个传送门
34、ScrollView 不能嵌套使用flatList
ScrollView 中不能使用flatList,会报错。虽然ScrollView 加flatList 的应用场景非常多,社区反馈也很多。但是官方还是没有什么解决方案,想要在flatList 中插入想要滚动的内容只能使用flatList 提供的headerRender和footerRender。 但是这样会出现问题,一旦list 更新,你的内容就会一起刷新
35、react-native-swiper建议不要使用
。react-native-swiper 有9.8k star,但是社区不活跃,很多issue未解决。最后更新时间也在2020年。 而且问题也很多: 1、初始化的时候必须有值,如果没有值的话就会出很多奇奇怪怪的bug。但是这个必须有值也是社区issue提出的 2、重复刷新的时候会计算错误 建议使用react-native-EzSwiper
36、textInput存在在modal上 autoFocus 不能弹出
需要使用ref+ setTimeout() textInput 的autoFocus属性会弹出软键盘。但是如果textInput在modal上。autoFocus 属性就会失效,软键盘不会弹出。解决方案为在使用ref,异步设置focus
37、“parserOptions.project“ has been set for @typescript-eslint/parser
这个问题查阅type-eslint官方的资料以及issue。发现是一个常驻的问题。且官方不会解决。导致的问题的原因是同意个目录下存在两个名字相同的文件。 但是问题是目录下没有两个一样的文件也会出现这个问题。type-eslint 的解析器需要设置tsconfig。tsconfig 需要指明include那些文件。如果没有包含就会报错。