一、Text增加点击态效果
在RN里,我们经常会遇到点击文字或者按钮有响应的。其中,我们的一些按钮是Text+style 去实现一个按钮样式的。当我们点击文字的时候,会出现只有文字被选中的阴影,而不是覆盖到整个按钮上的。
第一个反应就是Text没覆盖,或者我们需要在上面蒙上一层全覆盖的蒙层。由于View标签在onPress响应无效且不好写点击态样式,我们可以采取Touch系列的组件,这里可以说下几个值得注意的点:
- TouchableOpacity 里的activeOpacity 这个属性很好用,当activeOpacity = 1时可以实现失效按钮的效果,不带透明度。
- 在React Native 官方文档中,有提到过关于Touchable 系列组件不能很好的响应,具体表现就是:有些时候,如果我们有一项操作与点击事件所带来的透明度改变或者高亮效果发生在同一帧中,那么有可能在onPress函数结束之前我们都看不到这些效果。特别是真机上的时候,时好时坏。当然,官方也给出了相关解决方案。对此的一个解决方案是将onPress处理函数中的操作封装到requestAnimationFrame中,
handleOnPress() {
// 谨记在使用requestAnimationFrame、setTimeout以及setInterval时
// 要使用TimerMixin(其作用是在组件unmount时,清除所有定时器)
this.requestAnimationFrame(() => {
this.doExpensiveAction();
});
}
这里所要解决的就是一个掉帧的问题,这里也不再细述,有兴趣想了解的可以移步官网性能篇。
二、定时器
看到第一个问题的时候,就看到了官网的解决方案里有一句,在组件unmount时,清除所有定时器!!!这里提示了我,我在项目里,也有些setTimeout和setInterval是没有在unmount时,去清除的。因为我们发现很多 React Native 应用发生致命错误(闪退)是与计时器有关,这很难受,且致命。这里就列一个清除的小栗子🌰吧~~
import React, { Component } from "react";
export default class Hello extends Component {
componentDidMount() {
this.timer = setTimeout(() => {
console.log("把一个定时器的引用挂在this上");
}, 500);
}
componentWillUnmount() {
// 请注意Un"m"ount的m是小写
// 如果存在this.timer,则使用clearTimeout清空。
// 如果你使用多个timer,那么用多个变量,或者用个数组来保存引用,然后逐个clear
this.timer && clearTimeout(this.timer);
}
}
三、console问题
“快来看,快来看,卡死了卡死了,根本就不能动啊~~”,测试小伙伴跑过来跟我讲,并递过来一个仿佛时间停滞50倍的ios。我特么就是一脸问号,“不是吧,我提交的时候,还是好好地啊,我就是修改了一下要修改的字段啊,怎么这么卡??”
“不慌不慌,我瞅瞅”,实则内心慌得一比!!就在我的模拟器上实操了一下,“哎~~没问题啊,很流畅。” 这就纳了闷儿了。我就比较了一下提交,发现除了改个字段以外,我还打印了一句console.log(“props”,this.props),心里还想,难道是这个console搞得鬼,我立马就弄起注释来了,提交后发现哎哟,还真是console的原因。打发走测试后,我就来找原因,后来发现,这里的this.props对象内容过多,拖累了js进程,导致的卡顿。所以,我就全局修改了所有的console。
但是问题来了,没了console,调试起来真的是很麻烦,每次改东西的时候,会去打开,然后提交的时候,都注释掉,这样就很“人工”,很不安全。毕竟谁都不好保证每次都记得。
其实这些东西,很多大佬们早就想好了,我们只要去找轮子就好,更何况,写在了官网上,在运行打好了离线包的应用时,控制台大量打印语句可能会拖累 JavaScript 线程。注意有些第三方调试库也可能包含控制台打印语句,比如redux-logger,所以在发布应用前请务必仔细检查,确保全部移除。
有个babel 插件可以帮你移除所有的console.*调用。首先需要使用yarn add --dev babel-plugin-transform-remove-console来安装,然后在项目根目录下编辑(或者是新建)一个名为·.babelrc`的文件,在其中加入:
{
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
这样在打包发布时,所有的控制台语句就会被自动移除,而在调试时它们仍然会被正常调用。
四、app引导页
在app每次下载的第一次打开,都会有个引导页,来引导用户去第一时间了解app或者去咨询用户所需要的相关硬件权限授权。开始想得比较简单,就是用一个storage的值来存一个值,判断是否是第一次打开。然后navigation里把引导页设置为初始页。然后判断storage的值再进行跳转到首页。但是,这个在首页没有禁止滑动的情况下,右滑是可以返回到上一页(引导页的,且多为空白屏)。
于是,我熟练地打开了github,搜了个引导页的组件,就装了进来。哈哈~~万能的github。也不说什么废话了,有需要的可以自取:新手引导页组件
五、webview 插入js
产品中,遇到过这么个问题,就是运营那边上传的一些用户协议,合同条款这些文件的时候,字体太小。且在后端只是简单的做一个文件存储的情况下,这种变大字体的活儿只能落到我们前端肩上了。
RN是打开了一个Webview,source链到对应的资源上的。前期我们有个类似的需求,就是文章滑到地步看完后,webview外面的按钮才能高亮点击。
Webview里的这个injectedJavaScript属性,就是会去写入的js。但是,我在写入后发现,injectedJavaScript不生效了。哪怕是一个简单的console,都没有执行。我这就很无语。以为是执行顺序的问题。以下是我的injectedJavaScript的值:
`window.οnlοad=function(){
document.getElementsByTagName('body'[0].style.webkitTextSizeAdjust= '300%';
};true;`
对的,injectedJavaScript这里的属性值就是一个字符串,但是,这样就是没有生效。然后我又加了个window.onload() 再去触发下:
`window.οnlοad=function(){
document.getElementsByTagName('body'[0].style.webkitTextSizeAdjust= '300%';
};
window.onload();
true;`
发现依然无效,我就担心是不是url里的文件有问题,我换了个链接,去网站上随便找了个在线新闻的链接,放进去。哎哟,放大了。
这就是一个很好的信号,告诉我,injectedJavaScript这个方法,且我写的js是可以执行的。那我们接着找原因。难道真的是后端返回链接问题。仔细一看才发现,后端返回的协议是以.htm结尾的。不是一个链接,而是一个静态资源,需要我们去下载的,所以应该就是这里的问题了。
那问题就好说了,我们在点击弹出Webview框展示内容的时候,先把资源下载下来,然后再对他进行js插入。
ok~~搞定。
后续:后面一些插入关于用户信息的数据时,也是用这个思路和方法解决的。
只是有一个小地方,需要注意下,那就是injectedJavaScript里都是字符串,如果传变量的话,不能简单的这样传入的,这样他会把传入的值变为字符串。
// name 是传入的变量值
`window.οnlοad=function(){
document.getElementsByTagName('body'[0].style.webkitTextSizeAdjust= '300%';
//let a = ${name}
let a = '${name}'
};
window.onload();
true;`
要在外面再包一层,这样才能解析好name这个变量了。😄
以上,为我现阶段整理的部分,只是想记录以下自己遇到的RN里的一些坑点,分享给大家,也希望和大家多交流~~还有许多东西要去了解和学习,以后也会持续更新,道阻且长!
纪念下,ios版本的App终于上线啦!!希望越来越好~~
本文记录了React Native开发中的一些常见问题和解决方案,包括Text点击态效果的实现,避免定时器导致的内存泄漏,控制台打印影响性能的处理,app引导页的实现,以及在Webview中插入JS脚本调整字体大小的技巧。通过这些经验分享,旨在帮助开发者更好地理解和解决RN开发中的问题。
420

被折叠的 条评论
为什么被折叠?



