网络编程
位置:首页>> 网络编程>> JavaScript>> 编写一个JS组件来说说call和apply的用法(3)

编写一个JS组件来说说call和apply的用法(3)

作者:ComPhilip 来源:经典论坛 发布时间:2008-11-23 17:11:00 

标签:call,apply,组件,函数,用户

接着看看

AddInvalidTypeEventHandler : function(handler){//添加非法数据类型处理函数
        if (typeof(handler)!='function')
            throw new Error('参数handler必须为函数');
        this._invalidTypeHandler.Add(handler);
    },
    RemoveInvalidTypeEventHandler : function(handler){//移除非法数据类型处理函数
        if (typeof(handler)!='function')
            throw new Error('参数handler必须为函数');
        this._invalidTypeHandler.Remove(handler);
    },
    AddOverflowEventHandler : function(handler){//添加溢出处理函数
        if (typeof(handler)!='function')
            throw new Error('参数handler必须为函数');
        this._overflowHandler.Add(handler);
    },
    RemoveOverflowEventHandler : function(handler){//移除溢出处理函数
        if (typeof(handler)!='function')
            throw new Error('参数handler必须为函数');
        this._overflowHandler.Remove(handler);
    },

这4个函数其实是对外提供两个事件:InvalidType和Overflow。现在对Array类进行扩展的两个方法:Add和Remove在这里用上了。由于IE不完美支持DOM事件模型,我们只好自己实现。

我们可以把多个函数绑定到一个事件中,而不用将代码全部挤在一个函数体内。通过Add***,我们可以往事件添加处理函数,当事件发生时,会逐个调用这些函数。通过Remove***,我们可以移除这些处理函数。在这里,造器中的两个数组——_invalidTypeHandler 和 _overflowHandler——是用来存放函数指针(function是一个对象,它是一个引用类型)的。

然后我们看看_init的内部方法:

_init : function(controlId,min,max){ //创建DOM
        this._dom = document.createElement('input');
        this._dom.type = 'text';
        this._dom.id = controlId;
        this._dom.name = controlId;
        this._dom.oNumTextBox = this;
        this._dom.onblur = this._checkValue;//事件绑定
        document.body.appendChild(this._dom);//放入网页中
    }

我想除了倒数第二、三句:this._dom.oNumTextBox = this;this._dom.onblur = this._checkValue,大家都明白其他语句的作用。这个方法是创建一个文本框,设定id和name属性,构造器的controlId参数赋给id属性,其他JS代码可通过document.getElementById来获得这个文本框。

this._dom.oNumTextBox = this; 这条代码是将NumTextBox类的一个实例对象附加到新创建的文本框的oNumTextBox属性中,之所以添加这个属性,待会说明。this._dom.onblur是绑定文本框失去焦点的事件,处理函数为NumTextBox的_checkValue方法。也就是说,我们封装验证代码的入口就在这里。通过把_checkValue绑定到文本框的事件上,我们可以搞许多花样。看看_checkValue怎么写的。

_checkValue : function(ext){//检查数据
        ext = ext ? ext : window.event;
        var oNumTextBox = this.oNumTextBox;
        if (this.value == "")
            return;
        if (isNaN(this.value)){
            oNumTextBox._raiseInvalidTypeEvent.apply(oNumTextBox,[ext]);
            return;
        }
        var value = this.value*1;
        if (!(value>=oNumTextBox._min && value <=oNumTextBox._max))
            oNumTextBox._raiseOverflowEvent.apply(oNumTextBox,[ext]);
    },

第一句大家都很明白,旨在消灭IE和Gecko核心在事件模型的差异。大家要特别注意这个函数中this的指向。在类模型的其他方法中,this指向类实例,但这里的this却是指向类创建的文本框对象(id为controlId的文本框)?为什么呢?因为这个_checkValue函数在绑定文本框的onblur事件,当文本框失去焦点时,浏览器会调用这个_checkValue,并把它的函数上下文(this)改为触发事件的html对象(也就是文本框)。所以this指向文本框。我们把许多的逻辑放到那个类对象上,那么如何找到那个对象呢?在_init中我们把类对象附加在文本框的oNumTextBox属性中,那么我们就可以通过this.oNumTextBox来获取。如_checkVallue的第二行代码所示。接着开始验证数据。

如果没有数据,则忽略(一个return直接退出).如果数据不是合法的数值,如"asdf",则调用触发InvalidType事件。所谓的触发,触发的动作就是调用_raiseInvalidTypeEvent的方法。朋友们,先暂时一下,在讲apply之前,说说事件的顺序。调用触发invalidType事件的函数后,我们直接return。这说明了两件事,invalidType事件和Overflow事件只能同时发生其中一个,而且InvaidType先发生。看看上面的代码是如何实现的。

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com