• jQuery源码学习10——和事件相关的方法


    jQuery的事件系统给每个通过jQuery.event.add()方式绑定事件的DOM对象生成了下面这种结构

    从这张图中可以看出,我们除了可以给元素添加像click mouseover mouseout这样的原生事件之外

    还可以添加selfEvent这样的自定义事件

    自定义事件需要手动通过trigger触发

    jQuery.macros = {
        each: {
            bind: function( type, fn ) {
                if ( fn.constructor == String )
                    fn = new Function("e", ( !fn.indexOf(".") ? "$(this)" : "return " ) + fn);
                jQuery.event.add( this, type, fn );
            },
    
            unbind: function( type, fn ) {
                jQuery.event.remove( this, type, fn );
            },
            trigger: function( type, data ) {
                jQuery.event.trigger( type, data, this );
            }
        }
    };

    很容易看出bind和unbind底层还是调用了add和remove方法

    再来看扩展的一些更顶层的方法

        new function(){
            var e = ("blur,focus,load,resize,scroll,unload,click,dblclick," +
                "mousedown,mouseup,mousemove,mouseover,mouseout,change,reset,select," + 
                "submit,keydown,keypress,keyup,error").split(",");
            for ( var i = 0; i < e.length; i++ ) new function(){
                    
                var o = e[i];
                jQuery.fn[o] = function(f){
                    return f ? this.bind(o, f) : this.trigger(o);
                };
                jQuery.fn["un"+o] = function(f){ return this.unbind(o, f); };
                jQuery.fn["one"+o] = function(f){
                    return this.each(function(){
                        var count = 0;
                        jQuery.event.add( this, o, function(e){
                            if ( count++ ) return;
                            return f.apply(this, [e]);
                        });
                    });
                };                
            };
        }

    类似$("#div1").click(function(){})这种方法也可以很明显看到click方法实际上是调用了bind方法,bind最后还会调用add方法去添加事件

    而$("#div1").click()就是手动触发绑定的事件,click里面通过判断是否有参数采取不同的操作

    但是类似unclick这个方法貌似是不能移除绑定的匿名方法的

    类似oneclick的这种方法是在调用add的时候又包装了一层,通过count来保证了它只调用一次

        _toggle: jQuery.fn.toggle,
        toggle: function(a,b) {
            return a && b && a.constructor == Function && b.constructor == Function ? this.click(function(e){
                this.last = this.last == a ? b : a;
                e.preventDefault();
                return this.last.apply( this, [e] ) || false;
            }) :
            this._toggle.apply( this, arguments );
        },

    toggle实在没什么好说的,源码很简单

        hover: function(f,g) {
            function handleHover(e) {
                var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
                while ( p && p != this ) p = p.parentNode;
                if ( p == this ) return false;
                return (e.type == "mouseover" ? f : g).apply(this, [e]);
            }
            return this.mouseover(handleHover).mouseout(handleHover);
        },

    hover里面处理了原生的onmouseover和onmouseout事件里面的一个问题

    通过一个例子说明问题:

        <script>        
        $(function(){
            $("#div1").hover(function(){
                $(this).css("background","#f00");
            },function(){
                $(this).css("background","#0f0");
            });
        });
        </script>
    <div id="div1"> <div id="div2"> <div id="div3"></div> </div> </div>

    这个代码明显是希望移入#div1的时候变成红色,移出的时候变成绿色

    以移出(onmouseout)为例,从#div1移出的时候如果移到了#div1外面肯定是会触发onmouseout事件的

    但是移到#div2或#div3的话也会触发onmouseout事件的

    而后一种情况往往是不希望出现的

    也就是说移动到#div1的子元素上我们不希望触发onmouseout事件

    在hover内部我们可以看到当触发onmouseout事件的时候(e.type为"mouseout")变量p存储的是e.toElement||e.relatedTarget(这种写法必定是为了兼容了)

    从toElement名字上可以猜测,p存储的应该是移动到了哪个元素上面,在这个例子中p可能是document.body,可能是#div2,可能是#div3

    接下来是一个while循环,看当前的p是不是等于this,this即触发onmouseout的元素,在这里自然是#div1

    第一次循环不论是移动到了document.body上、还是#div2上、还是#div3上都不会等于this

    所以执行循环体里面的内容p=p.parentNode

    接下来的循环我们通过分析可以明白:如果p是document.body的话循环会直接结束

    而且往下走也不会满足p==this的条件,那就直接执行我们mouseout绑定的函数

    如果p是#div2或#div3的时候p最终会指向#div1

    再往下走就满足了p==this的条件,从而直接return false回去

    什么都不执行

    mouseout到此为止就分析完了,mouseover和它同理

  • 相关阅读:
    css的三种方法以及优先级说明
    form表单中的label标签
    html 中 a 标签 mailto的用法
    Hexo + GitHub Pages搭建博客
    Sublime Text3使用指南
    IMU数据融合:互补,卡尔曼和Mahony滤波
    正点原子STM32探索者学习笔记4
    正点原子STM32探索者学习笔记3
    正点原子STM32探索者学习笔记2
    正点原子STM32探索者学习笔记1
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/4997409.html
Copyright © 2020-2023  润新知