利用DeviceEventEmitter解决标题栏和数据列表联动问题
来源:互联网 发布:vue app.js报错 编辑:程序博客网 时间:2024/05/19 18:13
分析
页面包含TitleBar和TabNavigator组件,同时TabNavigator包含三个MessageScreen组件,而在MessageScreen中是FlatList组件,其中的Item是自定义的MessageItem组件。所以嵌套层次还是挺多的。而要实现动画中的效果,需要点击TitleBar中的编辑按钮,刷新MessageItem的状态。此处采用DeviceEventEmitter相对简单点。
当然,如果有更好的方法欢迎交流。
源码
MessageWrapperScreen.js
import React from 'react';import {StyleSheet, Text, View, ToastAndroid, BackHandler, DeviceEventEmitter, PixelRatio} from 'react-native';import {TabNavigator} from 'react-navigation';import TitleBar from "../components/TitleBar";import MessageScreen from "./MessageScreen";import theme from "../style/theme";import Constant from "../Constant";import BottomButton from "../components/BottomButton";const MessageNavigator = TabNavigator({ Tab1: { screen: MessageScreen, navigationOptions: ({navigation}) => ({ tabBarLabel: '全部消息' }) }, Tab2: { screen: MessageScreen, navigationOptions: ({navigation}) => ({ tabBarLabel: '销售运营通知' }) }, Tab3: { screen: MessageScreen, navigationOptions: ({navigation}) => ({ tabBarLabel: '小秘书通知' }) }}, { lazy: true, tabBarOptions: { activeTintColor: theme.activeColor, inactiveTintColor: theme.inactiveColor, upperCaseLabel: false, labelStyle: { fontSize: 12, marginTop: 0, marginBottom: 0, }, indicatorStyle: { backgroundColor: theme.activeColor }, style: { backgroundColor: '#FFF', height: 35, }, },});/** * 站内信Tab外层页面(包含TabNavigator) */export default class MessageWrapperScreen extends React.Component { constructor(props) { super(props) this.state = { isEditing: false,//是否正在编辑 } } render() { const navigation = this.props.navigation; return ( <View style={styles.container}> <TitleBar nav={navigation} title="站内信" rightText={this.state.isEditing ? "取消" : "编辑"} handleRightClick={this.handleEdit} handleBackClick={this.handleBackClick} /> <MessageNavigator navigation={navigation}/> {this.state.isEditing ? (<View style={{flexDirection: 'row', height: 40}}> <BottomButton title="全部已读" handleClick={this.handleAllRead} /> <View style={{width: 1/PixelRatio.get(), height: 40, backgroundColor: 'white'}}/> <BottomButton title="删除" handleClick={this.handleDelete} /> </View>) : null} </View> ); } handleEdit = () => { this._updateMessageList(); this.setState({ isEditing: !this.state.isEditing }); }; handleBackClick = () => { if (this.state.isEditing) { this._updateMessageList(); this.setState({ isEditing: false, }); } else { this.props.navigation.goBack(); } }; /** * 发送 * @private */ _updateMessageList = () => { DeviceEventEmitter.emit(Constant.EVENT_UPDATE_MESSAGE_LIST, !this.state.isEditing); //发监听 }; handleAllRead = () => { ToastAndroid.show('handleAllRead', ToastAndroid.SHORT) }; handleDelete = () => { ToastAndroid.show('handleDelete', ToastAndroid.SHORT) }}const styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'column' }, button: { color: 'white', }, buttonWrapper: { flex: 1, paddingLeft: 10, paddingRight: 10, justifyContent: 'center', alignItems: 'center', backgroundColor: theme.activeColor, }, btnContainer: { flex: 1, }});//https://reactnavigation.org/docs/intro/nestingMessageWrapperScreen.router = MessageNavigator.router;
扩展:【解决ReactNavigation中Navigator嵌套问题】
MessageScreen.js
import React from 'react';import { StyleSheet, View, FlatList, ActivityIndicator, ToastAndroid,} from 'react-native';import LoadingView from "../components/LoadingView";import MessageItem from "../components/MessageItem";import {requestMessageList} from "../request/Apis";export default class MessageScreen extends React.Component { constructor(props) { super(props); this.page = 1; this.state = { first: false,//首次加载,不渲染FlatList refreshing: false, loadMore: false, dataList: [], isEditing: false, } } componentDidMount() { // this.requestData(1) } _onPressItem = (msgId) => { const {navigate} = this.props.navigation; console.log(this.props.navigation); navigate('MessageDetails', {'msgId': msgId}) }; _renderItem = (item, index) => ( <MessageItem editable = {this.state.isEditing} data={item} onPressItem={this._onPressItem} /> ); _dividerLine = () => (<View style={{height: 2}}/>); _emptyComponent = () => (<LoadingView/>); _onRefresh = () => { this.setState({ refreshing: true }); this.requestData(1) }; _onEndReached = () => { if (!this.state.refreshing && !this.state.loadMore) { this.setState({ loadMore: true }); this.requestData(++this.page); } }; _onFooterComponent = () => { return this.state.loadMore ? ( <View style={styles.footerStyle}> <ActivityIndicator style={styles.indicatorStyle} size="large" /> </View> ) : null }; requestData = () => { requestMessageList().then((result) => { this.setState({ first: false, loadMore: false, refreshing: false, dataList: this.page === 1 ? result.data : this.state.dataList.concat(result.data), }) }, (error) => { this.setState({ first: false, loadMore: false, refreshing: false, }); ToastAndroid.show("error", ToastAndroid.SHORT); }); }; render() { let content; if (this.state.first) { content = (<LoadingView/>); } else { content = (<FlatList initialNumToRender={10} data={this.state.dataList} keyExtractor={(item, index) => item.relationId} renderItem={this._renderItem} onRefresh={this._onRefresh} refreshing={this.state.refreshing} ItemSeparatorComponent={this._dividerLine} onEndReachedThreshold={0.1} onEndReached={this._onEndReached} ListFooterComponent={this._onFooterComponent} />); } return ( <View style={{flex: 1}}> {content} </View> ); } // render(){ // return(<View/>) // }}const styles = StyleSheet.create({ footerStyle: { height: 50, alignItems: 'center', justifyContent: 'center', backgroundColor: '#DDD' }, indicatorStyle: { height: 40, alignItems: 'center', justifyContent: 'center' }});
MessageItem.js
import React from 'react';import {StyleSheet, View, Text, TouchableNativeFeedback, Image, Dimensions,DeviceEventEmitter, ToastAndroid} from 'react-native';import moment from 'moment';import CheckBox from './CheckBox';import Constant from "../Constant";export default class MessageItem extends React.Component { constructor(props) { super(props); this.state = { checked: false, isEditing: false, } } _onPress = () => { const item = this.props.data.item; this.props.onPressItem(item.relationId); }; componentWillMount() { this.listener = DeviceEventEmitter.addListener(Constant.EVENT_UPDATE_MESSAGE_LIST, (e) => { this.setState({ isEditing: e }); }); } onChange = (checked) => { this.setState({ checked: !this.state.checked, }); }; componentWillUnmount() { this.listener.remove(); } render() { const item = this.props.data.item; const time = moment(item.gmtCreate).format('YYYY-MM-DD'); return ( <TouchableNativeFeedback onPress={this._onPress} background={TouchableNativeFeedback.Ripple('#CCC', false)}> <View style={styles.itemContainer}> {this.state.isEditing ? (<View style={{marginRight: 5}}> <CheckBox label='' checked={this.state.checked} onChange={this.onChange} /> </View>) : null} <View style={{flex: 1}}> <View style={styles.itemTitleContainer}> <View style={{flexDirection: 'row', alignItems: 'center', flexShrink: 1,}}> {item.isRead == 0 ? <View style={styles.dot}/> : null} <Text style={styles.titleStyle} numberOfLines={1}>{item.title}</Text> </View> <Text style={[styles.contentStyle, {flexShrink: 0}]}>{time}</Text> </View> <Text style={[styles.contentStyle, {marginTop: 6}]} numberOfLines={2}>{item.summarize}</Text> </View> </View> </TouchableNativeFeedback> ); }}const styles = StyleSheet.create({ itemContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#FFF', padding: 8, }, itemTitleContainer: { flexDirection: 'row', justifyContent: 'space-between', }, titleStyle: { fontSize: 15, color: '#222', }, contentStyle: { fontSize: 13, color: '#BBB', }, dot: { width: 6, height: 6, borderRadius: 3, backgroundColor: '#FF0000', marginRight: 3 },});
核心代码
在MessageItem中添加时间监听,并在组件卸载后移除监听
componentWillMount() { this.listener = DeviceEventEmitter.addListener( Constant.EVENT_UPDATE_MESSAGE_LIST, (e) => { this.setState({ isEditing: e }); }); } componentWillUnmount() { this.listener.remove(); }
点击编辑按钮,触发事件
DeviceEventEmitter.emit( Constant.EVENT_UPDATE_MESSAGE_LIST, !this.state.isEditing); //发监听
阅读全文
0 0
- 利用DeviceEventEmitter解决标题栏和数据列表联动问题
- 利用中介者模式与观察者解决购物车与商品列表联动问题
- 如何利用Excel数据有效性制作多级联动下拉列表
- 下拉列表框联动问题
- 添加列表和省市联动
- React-Native 发送和接收事件DeviceEventEmitter
- 利用combobox联动本地JSON数据
- 【Android】自定义标题栏 (解决了标题栏两侧空隙问题)
- 利用js和css实现Bootstrap下拉列表数据过滤
- 解决列表框更新数据的时候的闪烁问题
- Fragment实现列表和内容联动
- ASP利用数据表生成多级联动下拉列表框
- 解决android自定义标题栏充满的问题
- 解决android自定义标题栏充满的问题
- 解决android自定义标题栏充满的问题
- 解决android自定义标题栏充满的问题
- 解决android自定义标题栏充满的问题
- 解决android自定义标题栏充满的问题
- spring @Qualifier注解
- 时间复杂度示例
- Android 集成高德地图(一)
- C语言 爱因斯坦阶梯问题
- MyEclipse6.5离线安装SVN插件
- 利用DeviceEventEmitter解决标题栏和数据列表联动问题
- Springboot 常用注解
- 快速搭建一个简单的springboot项目
- Windows系统,CentOS6.5, 7操作系统防火墙规则
- TCP粘包/拆包--利用LineBasedFrameDecoder解决TCP粘包问题
- 弹性动画
- 渐变色与圆角显示(填充,描边)
- 14种模型设计帮你改进你的卷积神经网络(CNN)
- cl命令行编译C++程序