问题描述,关于react-navigation 导航库在快速连续点击的时候,叶面会发生多次跳转,初次遇到这个坑爹的问题时,一脸懵逼,看过源码,几经折腾终于弄明白了是咋会儿事儿
问题出现的原因:
node_modules/react-navigation/src/NavigationActions.js 下的部分代码
// 罪魁祸首是因没有针对该事件做相应的延迟处理,用源码可以看到,每次点击都会触发该事件,只要路由构长,这种bug必然
const navigate = payload => {
const action = {
type: NAVIGATE,
routeName: payload.routeName,
};
if (payload.params) {
action.params = payload.params;
}
if (payload.action) {
action.action = payload.action;
}
if (payload.key) {
action.key = payload.key;
}
return action;
};
直接解决方案:
- 直接改源码,但是不易维护(不建议)
- 自行封装进行控制
高阶组件统一封装,代码如下:
HOCTouchable.js
/** react 组建的引用 */
import React, { Component } from "react";
import { TouchableWithoutFeedback } from "react-native";
/** 第三方依赖库的引用 */
import PropTypes from "prop-types";
// 高阶组件的封装,为了满足所有类型以及点击事件
export default function HOCTouchable(TagComponent) {
class CTouchable extends Component {
static propTypes = {
disabled: PropTypes.bool,
onPress: PropTypes.func
};
static defaultProps = {
disabled: false,
onPress: null
};
constructor(props) {
super(props);
this.timer = null;
this.isJump = true;
}
/** 判断是否允许进行页面的跳转 */
_isAllowToJump = () => {
if (this.isJump) {
this._changeJump();
return true;
} else {
return false;
}
};
/** 通过定时器来控制页面的跳转,防止react-navigation连续快速点击会导致页面多次跳转 */
_changeJump = () => {
this.isJump = false;
this.timer = setTimeout(() => {
this.isJump = true;
clearTimeout(this.timer);
this.timer = null;
}, 500);
};
_onPress = () => {
const { handle } = this.props;
this._isAllowToJump() && handle instanceof Function && handle();
};
render() {
return <TagComponent {...this.props} onPress={this._onPress} />;
}
}
return CTouchable;
}
用法如下
xxx.js
import React, {Component} from "react";
import {TouchableWithoutFeedback,Linking, TouchableHighlight, TouchableOpacity} from "react-native";
import HOCTouchable from 'xx/CTouchable'; // 根据自己也页面的相对路径进行引用
const CTouchableWithoutFeedback = HOCTouchable(TouchableWithoutFeedback)
// 根据实际开发,根据高阶组件生成经过封装的新的点击按钮
// 简单的使用介绍到这里
render () {
return (
<CTouchableWithoutFeedback
handle={() => {
this.props.navigation.navigate('AccountInfo', this.state.userInfo)
}}>
<View style={{
width: 116, height: 116,
position: 'relative',
marginLeft: 23,
justifyContent: 'flex-end',
}}>
<ImageBackground
fadeDuration={0}
style={[styles.avatarbg, styles.imgPos]}
source={require('../../images/common/common_shadow_abatar.png')}>
<View style={styles.avatarbg_ar_wrap}>
<Image
fadeDuration={0}
style={[styles.avatarbg_ar, {borderRadius: 50}]}
source={headPicture ? {uri: headPicture} : require('../../images/me/index_icon_bixia.png')}/>
</View>
</ImageBackground>
<ImageBackground
fadeDuration={0}
style={[styles.imgPos, styles.avatarbg,]}
source={require('../../images/me/me_img_headmask.png')}
>
</ImageBackground>
</View>
</CTouchableWithoutFeedback>
)
}
更多的干货请点击这里
react-native 实战项目demo
欢迎各位看官的批评和指正,共同学习和成长
希望该文章对您有帮助,也希望得到您的鼓励和支持