react-navigation 連續點選多次跳轉
阿新 • • 發佈:2019-01-09
問題描述,關於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
歡迎各位看官的批評和指正,共同學習和成長
希望該文章對您有幫助,也希望得到您的鼓勵和支援