zoukankan      html  css  js  c++  java
  • 一不小心翻车了-(angularjs 1.6X) 由Eventbus使用异常说起

    一  在angular框架使用过程中,我们经常碰到控制器之间进行通信的问题,

    方法有多种,今天记录的是通过factory通信,先上代码:

    //控制器之间共享
    angular.module('app').factory("EventBus", function() {
       
        var eventMap = {};    
        var EventBus = {
         
      on : function(eventType, handler) {
                
           if (!eventMap[eventType]) 
        {
               eventMap[eventType] = [];
           }
         eventMap[eventType].push(handler);
       },
    
       off : function(eventType, handler) {
           for (var i = 0; i < eventMap[eventType].length; i++) 
        {
                if (eventMap[eventType][i] === handler) {              
                    eventMap[eventType].splice(i, 1);
                     break;
                }
            }   
       },
         fire :
    function(event) { var eventType = event.type; if (eventMap && eventMap[eventType]) { for (var i = 0; i < eventMap[eventType].length; i++) { eventMap[eventType][i](event); } }   } }; return EventBus; });

    调用发布事件时候

    angular.module('app').controller('testcontroller',function($scope,$state,EventBus) {
        //发布事件
        EventBus.fire({
            type:'testevent',
            data:{
                List:1
            }
        })    
    });

    调用监事件听时候

    angular.module('app').controller('testcontroller',function($scope,$state,EventBus) {     
            
        EventBus.on("testevent",function(event){
            var data=event.data;        
            console.log(data);
        });
    });

    这个方法可以在多个地方监听同一个事件,代码又简练,在项目中用的很舒服

    二 但是用起来之后问题来了,主要有2个BUG

      第一个就是off取消事件

      off : function(eventType, handler) {
           for (var i = 0; i < eventMap[eventType].length; i++) 
        {
               //这个判断对比的是2个函数,永远都是false
                if (eventMap[eventType][i] === handler) {              
                    eventMap[eventType].splice(i, 1);
                     break;
                }
            }   
       },    

     取消时判断对比的是2个函数,永远都是false。 这个问题简单的解决方法就是把2个函数转化成string 再对比

     代码如下

    off : function(eventType, handler) {
                
                for (var i = 0; i < eventMap[eventType].length; i++) {
    
                    if (eventMap[eventType][i].toString() === handler.toString()) {
                        eventMap[eventType].splice(i, 1);
                        break;
                    }
                }
            },

    更完善的函数比较可以引用函数对比函数

    /**
         * 返回指定变量的数据类型
         * @param  {Any} data
         * @return {String}
         */
        function type (data) {
            return Object.prototype.toString.call(data).slice(8, -1);
        }
            
        
        /**
         * 对比两个function是否一样
         * 主要对比两者toString是否一样,
         * 对比会去掉函数名进行对比,其它哪怕差个回车都会返回false
         * 
         * @param  {[type]} fn1
         * @param  {[type]} fn2
         * @return {[type]}
         */
        function equalFunction (fn1, fn2) {
            var type1 = type(fn1),
                type2 = type(fn2);
                
            console.log(type1,type2)
            if (type1 !== type2 || type1 !== 'Function') {
                return false;
            };
            if (fn1 === fn2) {
                return true;
            };
            var reg = /^function[s]*?([w]*?)([^)]*?){/;
            var str1 = fn1.toString().replace(reg,function ($,$1) {
                return $.replace($1,"");
            });
            var str2 = fn2.toString().replace(reg,function ($,$1) {
                return $.replace($1,"");
            });
            console.log(str1,str2);
            if (str1 !== str2) {
                return false;
            };
            return true;
        }
    
    
            off : function(eventType, handler) {
                
                for (var i = 0; i < eventMap[eventType].length; i++) {
                    //if (eventMap[eventType][i] === handler) {
                    if (equalFunction(eventMap[eventType][i],handler)) {
                    //if (eventMap[eventType][i].toString() === handler.toString()) {
                        eventMap[eventType].splice(i, 1);
                        break;
                    }
                }
            },

    这个解决方案相对比较完善一些

    三  第二个Bug就比较致命了

    一开始我发现on监听执行过程中 获取的$scope 变量的值不是最新的!!! 差点让我怀疑人生。

    仔细研究之后发现同一个on监听执行了好多次(呵呵哒)

    原因在于 通信监听的on事件 注册了多次!!!

    注册多次是由于on所在的controller对应的页面     通过$state.go可跳转至其它页面  也可以跳转回来

    跳转回来多次 同一个on监听就被注册了多次 ,而且每次的on监听封装的$scope变量都是当次跳转到其它页面之前的值

    最后fire事件发布时,on就会有多个监听依次之下(同一个on监听事件 执行多次 但是每次的$scope变量可能不一样)

    so........我们在注册on事件时候需要查看下是否已经注册过该事件了 。。。。然后删除旧的 注册最新的(封装了最新的$scope变量)

    代码

            on : function(eventType, handler) {
                
                if (!eventMap[eventType]) {
                    eventMap[eventType] = [];
                }
                //注册on事件时候需要查看下是否已经注册过该事件了 。。。。然后删除旧的 注册最新的(封装了最新的$scope变量)
                this.off(eventType, handler);
                
                eventMap[eventType].push(handler);
            
            },

    四 修复Bug之后  开车的代码如下  又可以愉快的发车咯

    //控制器之间共享
    angular.module('yun.homework').factory("EventBus", function() {
       
        var eventMap = {};
    
        /**
         * 返回指定变量的数据类型
         * @param  {Any} data
         * @return {String}
         */
        function type (data) {
            return Object.prototype.toString.call(data).slice(8, -1);
        }
            
        
        /**
         * 对比两个function是否一样
         * 主要对比两者toString是否一样,
         * 对比会去掉函数名进行对比,其它哪怕差个回车都会返回false
         * 
         * @param  {[type]} fn1
         * @param  {[type]} fn2
         * @return {[type]}
         */
        function equalFunction (fn1, fn2) {
            var type1 = type(fn1),
                type2 = type(fn2);
                
            console.log(type1,type2)
            if (type1 !== type2 || type1 !== 'Function') {
                return false;
            };
            if (fn1 === fn2) {
                return true;
            };
            var reg = /^function[s]*?([w]*?)([^)]*?){/;
            var str1 = fn1.toString().replace(reg,function ($,$1) {
                return $.replace($1,"");
            });
            var str2 = fn2.toString().replace(reg,function ($,$1) {
                return $.replace($1,"");
            });
            console.log(str1,str2);
            if (str1 !== str2) {
                return false;
            };
            return true;
        }
        
        var EventBus = {
            on : function(eventType, handler) {
                
                if (!eventMap[eventType]) {
                    eventMap[eventType] = [];
                }
                this.off(eventType, handler);
    
                eventMap[eventType].push(handler);
    
            },
    
            off : function(eventType, handler) {
                
                for (var i = 0; i < eventMap[eventType].length; i++) {
                    //if (eventMap[eventType][i] === handler) {
                    //if (equalFunction(eventMap[eventType][i],handler)) {
                    if (eventMap[eventType][i].toString() === handler.toString()) {
                        eventMap[eventType].splice(i, 1);
                        break;
                    }
                }
            },
    
            fire : function(event) {
            
                var eventType = event.type;
                if (eventMap && eventMap[eventType]) {
            
                    for (var i = 0; i < eventMap[eventType].length; i++) {
                        eventMap[eventType][i](event);
                    }
                }
            }
        };
        return EventBus;
    });
  • 相关阅读:
    SpringMvc的服务器端跳转和客户端跳转
    springMvc的一些简介 和基于xml的handlerMapping基本流程
    springMvc 的参数验证 BindingResult result 的使用
    SpringMVC 学习笔记(二) @RequestMapping、@PathVariable等注解
    springmvc处理ajax请求
    取maven copy部分
    maven scope含义的说明
    Maven依赖中的scope详解
    EasyMock 使用方法与原理剖析
    Maven:Generating Project in Batch mode 卡住问题
  • 原文地址:https://www.cnblogs.com/mengsx/p/6696809.html
Copyright © 2011-2022 走看看