• React Native之DeviceEventEmitter发送和接收消息完成事件处理


    今天在Demo这样一个项目的时候,首先遇到的第一个问题就是,每次通过dialog选择【本周、本月、本天】时,伴随着内容重新渲染的时候,tab navigator每次都重新创建和渲染,造成性能浪费和用户体验差的问题

    问题分析:

    由于tab navigator是在render()函数中动态创建的,因此每次随着状态的改变,render都会重新渲染,从而导致的问题是,每次都要重新动态创建tab navigator。

    解决方案

    将创建好的tabNav给绑定到当前this上,如果当前tabNav已经存在,则直接返回。

    伪代码

    export default class TrendingPage extends Component<Props> {
        constructor(props) {
    	super(props);
            this.tabNames = ['All', 'C', 'C#', 'PHP', 'JavaScript'];
        }
     /**
         * 优化tabNav 避免每次render的时候都要重新动态的创建nav 
         * 
         *  优化效率:根据需要选择是否重新创建TabNavigator,通常tab改变后才重新创建
         * @returns
         * @memberof TrendingPage
         */
        _tabNav() {
            if (!this.tabNav) {
                this.tabNav = createMaterialTopTabNavigator(
                    this._genTabs(), {
                        tabBarOptions: {
                            tabStyle: styles.tabStyle,
                            upperCaseLabel: false, //是否标签大写,默认为true
                            scrollEnabled: true, // 选项卡排不下的时候,可以滚动,默认为false
                            style: {
                                backgroundColor: '#678',
                                height: 30,
                            },
                            indicatorStyle: typeAlias.indicatorStyle, // 标签指示器的样式
                            labelStyle: styles.labelStyle
                        }
                    }
                );
            }
            return this.tabNav;
        }
    
        _genTabs() {
    	const tabs = {};
    	this.tabNames.forEach((item, index) => {
    		tabs[`tab${index}`] = {
    			// screen: PopTab,
    			screen: props => <TrendingTabPage {...props} timeSpan={this.state.timeSpan} tabLabel={item} />,
    			navigationOptions: {
    				title: item
    			}
    		}
    	})
    	return tabs;
        }
    
        /* 省略其他代码*/
    }
    

    但是随之出现了接下来的问题,就是当我们通过在dialog选择完【本周】后,导航栏不变的情况下不重新动态创建了,下面的数据也不刷新了,从而导致该功能失效。

    问题分析

    由于带有信息list的screen是绑定在创建tab navigator中,因此当tab navigator不重新创建时,screen内容将不会重新渲染,那么我们又要保持当tab不改变的时候不重新创建和渲染,又想要当前tab下的内容根据用户操作而改变。

    解决方案

    使用react-native官方的一个API-----DeviceEventEmitter

    使用方法

    componentDidMount() {
            this.loadData();
            this.timeSpanChangeListener = DeviceEventEmitter.addListener(EVENT_TYPE_TIME_SPAN_CHANGE, (timeSpan) => {  //将监听事件绑定到当前this上的目的是在组件卸载时能撤销事件
                this.timeSpan = timeSpan;
                this.loadData();
            })
    	}
    
        componentWillUnmount() {
            if (this.timeSpanChangeListener) {
                this.timeSpanChangeListener.remove();
            }
        }
    

    DeviceEventEmitter.addListener()注册上事件,第一个参数是事件,第二个参数是事件触发时候的回调。注意在组件卸载时撤销事件的绑定,避免性能浪费。

        /**
         * 当从selection中选择一个触发的回调
         *
         * @param {*} tab 
         * @memberof TrendingPage
         */
        onSelectTimeSpan(tab) {
            this.dialog.dismiss();
            this.setState({
                timeSpan: tab
            });
            DeviceEventEmitter.emit(EVENT_TYPE_TIME_SPAN_CHANGE, tab)
        }
    
        /**
         * 创建一个TrendingDialog
         *
         * @returns
         * @memberof TrendingPage
         */
        renderTrendingDialog() {
            return <TrendingDialog
                ref={dialog => this.dialog=dialog}
                onSelect={tab=>this.onSelectTimeSpan(tab)}
            />
        }
    

    然后,我们给【本周、本天、本月】添加上回调onSelectTimeSpan,当用户操作的时候,触发回调,然后通过DeviceEventEmitter.emit()方法触发绑定的事件,执行回调,更新内容。

  • 相关阅读:
    SQL Server事务执行一半出错是否自动回滚整个事务 【转】
    html5 canvas做的俄罗斯方块
    laravel-admin 模型创建、数据迁移、以及关联模型控制器
    laravel-admin 安装
    Composer 安装时要求输入授权用户名密码?
    查找mysql中未提交的事务
    SSH 登录时出现如下错误:No supported key exchange algorithms
    MySQL运行一段时间后自动停止问题的排查
    浅谈PHP中的数组和JS中的数组
    MySQL中使用group_concat()函数数据被截取(有默认长度限制),谨慎!
  • 原文地址:https://www.cnblogs.com/fe-linjin/p/10617595.html
Copyright © 2020-2023  润新知