美文网首页
JavaScript进阶教程-4.dom零级 二级事件基础和实战

JavaScript进阶教程-4.dom零级 二级事件基础和实战

作者: 超跑飞飞 | 来源:发表于2020-02-21 11:38 被阅读0次

事件基础和事件委托

事件委托

事件的兼容性问题:
1、事件对象本身的获得方式不同,IE是用全局的window.event,chrome是浏览器自动会给把事件对象传给事件触发的方法,作为此方法的第一个参数。
1.1、chrome也是支持window.event的
2、事件传播和阻止事件传播的方式:ie是e.cancelBubble=true;标准浏览器是用的e.stopPropagation()
3、取消事件默认行为:IE是e.returnValue=false;标准浏览器用的是e.preventDefault();
4、触发事件的事件源不一样:IE是e.srcElement,标准浏览器是e.target
5、IE不支持e.pageX、e.pageY
6、最大的兼容性问题在于对DOM2级事件的支持上
什么DOM2级事件:就是在DOM的第二个版本中,实现的事件绑定方式
DOM0 (本身没有DOM0这么个概念,它是相对于DOM1来讲的) DHTML(动态HTML)
DOM是独立于JS之外的一个API,目的为了跨语言操作标记语言(主要是XML)应运而生的一种技术
DOM Core(DOM1):解决的文档的层次结构和增删改查的一些方法属性
DOM2 有一部分是实现更好的事件的解决方案
DOM3


document.body.form;
document.forms;
document.anchors;
document.all;
document.all["div1"]

document.onclick;
var ele=document.getElementById("div1");
function fn1(){alert(1);}
function fn2(){alert(2);}

var n=0;
//如果点击超过2次,则从事件移除些方法
function fn3(){
    n++;
    if(n==2){
        
    }
    alert(3);}
function fn4(){alert(4);}
ele.onclick=fn1;
ele.onclick=function(){fn1();fn2();fn3();fn4();}
//DOM2级事件的方法
EventTarget.prototype.addEventListener;
EventTarget.prototype.removeEventListener;
//DOM2级事件中新增加的事件类型
document.addEventListener("DOMContentLoaded",fn2,false);

//文档的中标签已经加载并解析(标签已经在网页上显示了)就触发些事件,至于外链的图片、样式、JS是否加载或运行,跟这个事件无关。
$(document).ready(function(e) {
    //"DOMContentLoaded"
    fn1
});
//$的参数如果是一个function,则表示文档内容加载完成之后运行此方法,也就是$(document).ready()这个事件,其实就是"DOMContentLoaded"这个事件
$(fn1);//这个表示内容加载完成之后,触发fn2这个方法,相当于下面
$(document).ready(fn2);

//以下
$("#div1").click(fn1);
$("#div1").click(fn2);
ele.addEventListener("click",fn1,false);
ele.addEventListener("click",fn2,false);
//浏览器的所有资源都已完成加载(当然,会有加载失败的:超时),触发onload事件
window.onload;

for(var i=0;true;i++){
    console.log(i); 
}

document.addEventListener("DOMContentLoaded",function(){alert("ContentLoaded");},false)


dom二级事件兼容问题


var ele=document.getElementById("div1");
function fn1(){alert(1);}
function fn2(){alert(2);}

var n=0;
//如果点击超过2次,则从事件移这个方法
function fn3(){
    n++;
    if(n==2){//第二次执行的时候执行移除,到第三次的时候生效
        this.removeEventListener("click",fn3,false);
    }
    alert(3);}
function fn4(){alert(4);}
ele.addEventListener("click",fn1,false);//第三个参数是指:是否在捕获阶段绑定此方法
ele.addEventListener("click",fn2,false);
ele.addEventListener("click",fn3,false);
ele.addEventListener("click",fn4,false);

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style type="text/css">
#div1{ height:100px; background:red;}
</style>
</head>

<body>
<div id="div1">div1</div>
</body>
</html>
<script>
var ele=document.getElementById("div1");
function fn1(){alert(1);}
function fn2(){alert(2);}

var n=0;
//如果点击超过2次,则从事件移这个方法
function fn3(){
    n++;
    if(n==2){//第二次执行的时候执行移除,到第三次的时候生效
        //this.removeEventListener("click",fn3,false);
        unbind(ele,"click",fn3);
        //不能把上一行代码中的ele换成this
    }
    alert(3);}
function fn4(){alert(4);}
function fn5(){alert(5);}
function fn6(){alert(6);}
function fn7(){alert(7);}
function fn8(){alert(8);}
function fn9(){alert(9);}
function fn10(){alert(10);}
function fn11(){alert(11);}
function fn12(){alert(12);}
bind(ele,"click",fn1);
bind(ele,"click",fn2);
bind(ele,"click",fn3);
bind(ele,"click",fn4);
bind(ele,"click",fn5);
bind(ele,"click",fn6);
bind(ele,"click",fn7);
bind(ele,"click",fn8);
bind(ele,"click",fn9);
bind(ele,"click",fn10);
bind(ele,"click",fn11);
bind(ele,"click",fn12);
function bind(ele,type,handler){//handler直译为句柄,方法名,方法引用的意思
    if(ele.addEventListener){
        ele.addEventListener(type,handler,false);   
    }else if(ele.attachEvent){
        ele.attachEvent("on"+type,handler);
    }
    
}

    function unbind(ele,type,handler){
        if(ele.removeEventListener){
            ele.removeEventListener(type,handler,false);
        }else if(ele.detachEvent){
            ele.detachEvent("on"+type,handler);
        }
    }

</script>

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style type="text/css">
#div1{ height:100px; background:red;}
</style>
</head>

<body>
<div id="div1">div1</div>
</body>
</html>
<script>
var ele=document.getElementById("div1");
function fn1(){
    this.innerHTML="点过"+n;
    alert(1);}
function fn2(){alert(2);}

var n=0;
//如果点击超过2次,则从事件移这个方法
function fn3(){
    n++;
    if(n==2){//第二次执行的时候执行移除,到第三次的时候生效
        //this.removeEventListener("click",fn3,false);
        unbind(this,"click",fn3);//
        unbind(this,"click",fn2);
        //不能把上一行代码中的ele换成this
        //执行bind的时候,第一次fnTemp是fn1的变形
        //              第二次fnTemp是fn2的变形
        //              第三次fnTemp是fn3的变形
    }
    alert(3);}
function fn4(){alert(4);}
function fn5(){alert(5);}
function fn6(){alert(6);}
function fn7(){alert(7);}
function fn8(){alert(8);}
function fn9(){alert(9);}
function fn10(){alert(10);}
function fn11(){alert(11);}
function fn12(){alert(12);}
bind(ele,"click",fn1);
bind(ele,"click",fn2);
bind(ele,"click",fn3);
/*bind(ele,"click",fn4);
bind(ele,"click",fn5);
bind(ele,"click",fn6);
bind(ele,"click",fn7);
bind(ele,"click",fn8);
bind(ele,"click",fn9);
bind(ele,"click",fn10);
bind(ele,"click",fn11);
bind(ele,"click",fn12);*/
var fnTemp=null;
function bind(ele,type,handler){//handler直译为句柄,方法名,方法引用的意思
    if(ele.addEventListener){
        ele.addEventListener(type,handler,false);   
    }else if(ele.attachEvent){
        
        //1、事件触发的时候handler方法执行
        //2、让handler方法里的this指向ele
        
        //记好一个原则:如果是解决this关键字的指向,则记好用call或apply方法
        
        //以下的处理方式已经就可以实现让事件触发的时候,handler里的this指向ele了。如果就是解决仅仅是解决this关键字关键,已经就解决了
        
        //即可以把fnTemp保存下来,还要保证fnTemp的安全,还要把多次变形得成的fnTemp都可以保存下来,并且在unbind里还可以识别出来当前这个fnTemp是由那个方法变形而来
        //ele.abindclick=[];//自定义属性
        //if(!ele.abindclick){
            /*ele[handler]
            ele[fn1]
            ele["fn1"]
            fn1=function(){};
            fn2=function(){};*/
        if(!ele["abind"+type]){
            //这个自定义属性的命名规则是:abind是属性的前缀,click是属性的区分符
            //ele.click
            //为什么要用click来命名呢?把绑定在不同事件类型上的方法,以事件类型做为命名的依据来定义不同的数组,来保存不同的事件上的方法。
            //但是我们又不能直接用事件类型作属性,容易和系统属性引起冲突,所以才在它前面加个前缀(为了让属性名变长,降低冲突的机率)
            //ele[type]=[];
            
            ele["abind"+type]=[];   
        }
        var fnTemp=function(){handler.call(ele);};
        fnTemp.photo=handler;//photo"照片",保存着它原来的面貌
        ele["abind"+type].push(fnTemp);
        ele.attachEvent("on"+type,fnTemp);
    }
    
}

    function unbind(ele,type,handler){
        if(ele.removeEventListener){
            ele.removeEventListener(type,handler,false);
        }else if(ele.detachEvent){
            var a=ele["abind"+type];
            //a里的第i项可能就是handler变形而来
            //a[i]==handler
            //现在需要一个机制,能识别出a[i]是由handler变形来的
            if(a){
                for(var i=0;i<a.length;i++){
                    if(a[i].photo==handler){
                        ele.detachEvent("on"+type,a[i]);
                        return; 
                    }
                }
            }
            //ele.detachEvent("on"+type,fnTemp);
        }
    }

</script>

实战 面向对象的拖拽功能开发

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style type="text/css">
div{ width:100px; height:100px; position:absolute; background:green; top:100px; left:100px; cursor:move; -webkit-user-select:none;}
</style>
</head>

<body>
<div id="div1" style="left:0; top:0; background:red;"></div>
<div id="div2"><img src="" height="100" width="100"></div>
<div id="div3" style="top:200px; left:150px; background:blue;"></div>
</body>
</html>
<script src="event1.js"></script>
<script>
//面向对象的编程强在管理、拓展功能。强项不是逻辑
//在使用面向对象编程方式之前,先要确定设计原则:this关键字的问题。
    //this要指向当前类的实例,无论是构造函数还是原型函数,this都要指是指向类的实例。
    //这一点会和事件原则中this冲突,如果存在冲突,强制使this指向类的实例
//一但使用的面向对象,代码的可读性会变差。
//使用面向对象,要理解整个类的体系

function Drag(ele){//构造函数是初始化的作用
    this.x=null;
    this.y=null;
    this.mx=null;
    this.my=null;
    this.ele=ele;//把被拖拽的元素保存到当前实例的ele属性上,以便其类上的其它函数能够访问。如果不把ele保存到this.ele上,其它方法无法访问这个私有变量ele。一个方法里定义的变量或形参,都是私有变量,其它的函数里无法访问;但如果我们把一个值保存到this的属性,则这个属性就成了公有变量
    /*
    function processThis(fn,obj){
        //返回的新方法:让fn的功能不变,但是this被强制改变了
        return function(e){fn.call(obj,e);this} 
        function fn1(){
            this;
            fn();   
        }
    }
    */
    this.DOWN=processThis(this.down,this);
    //processThis会返回一个新的方法,这个新的方法里还是执行老的方法this.down,但是会让this.down里的this一定指向当前类的实例
    this.MOVE=processThis(this.move,this);
    this.UP=processThis(this.up,this);
    
    on(ele,"mousedown",this.DOWN);
    //以下是错误的绑定方式
    //on(ele,"mousedown",this.down);//我们原则是:down方法无论在什么情况下里的this都指向类的实例this
    
    
    
    
}

Drag.prototype.down=function(e){
    this.x=this.ele.offsetLeft;
    this.y=this.ele.offsetTop;
    this.mx=e.pageX;
    this.my=e.pageY;
    
    if(this.ele.setCapture){
        this.ele.setCapture();
        on(this.ele,"mousemove",this.MOVE);
        on(this.ele,"mouseup",this.UP);
    }else{
        on(document,"mousemove",this.MOVE);
        on(document,"mouseup",this.UP);
    }
    e.preventDefault();
    //一定要注意的是:如果事件是用DOM2事件绑定方法来绑定的,那么阻止事件的默认行为一定要用e.preventDefault()这个方法
    
}
Drag.prototype.move=function(e){
    this.ele.style.left=this.x+e.pageX-this.mx+"px";
    this.ele.style.top=this.y+e.pageY-this.my+"px";
    
    
}
Drag.prototype.up=function(e){
    if(this.ele.releaseCapture){
        this.ele.releaseCapture();
        off(this.ele,"mousemove",this.MOVE);
        off(this.ele,"mouseup",this.UP);
    }else{
        off(document,"mousemove",this.MOVE);
        off(document,"mouseup",this.UP);
    }
}

var obj1=new Drag(div1);
//操作的主体,上下文,是ele这个dom元素;现在操作的主体是obj1这个对象,这个obj1中,承载了所有的和拖拽相关的信息(属性和方法)
new Drag(div2);
new Drag(div3);




</script>


相关文章

  • JavaScript进阶教程-4.dom零级 二级事件基础和实战

    事件基础和事件委托 事件委托 事件的兼容性问题:1、事件对象本身的获得方式不同,IE是用全局的window.eve...

  • JavaScript ☞ day3

    JavaScript基础学习笔记之JavaScript进阶 焦点事件 鼠标事件-单击与双击 鼠标事件-mouseo...

  • Vue基础篇(一)

    本教程分为三部分 : 基础 进阶 实战 ,深入浅出Vue.基础篇持续 更新中 --- vue.js的基本介绍和...

  • html5学习路线(粗略)

    ●HTML5+CSS3●常用浏览器兼容交互篇●JavaScript基础●DOM和BOM●动画特效●事件交互进阶篇●...

  • 技术栈

    一、HTML、CSS基础、JavaScript语法基础。 二、JavaScript语法进阶。包括:作用域和闭包、t...

  • 2020前端技术栈

    一、HTML、CSS基础、JavaScript语法基础。二、JavaScript语法进阶。包括:作用域和闭包、th...

  • 2.1Python进阶01 词典

    基础教程介绍了基本概念,特别是对象和类。进阶教程针对基础教程的进一步拓展,说明Python的细节。希望在进阶教程之...

  • Vue基础篇(五)

    本教程分为三部分 : 基础 进阶 实战 ,深入浅出Vue.js基础篇持续 更新中 ------ 列表渲染指令v-­...

  • javascript-事件基础和事件绑定

    javascript-事件基础和事件绑定 一、事件驱动 1.1事件 javascript侦测到的用户的操作(点击、...

  • python 中的动态属性和特性(Property)

    标题:property用法介绍。 实战: 这所有的python基础语法进阶语法都是应用于我所写的一个博客教程 博客...

网友评论

      本文标题:JavaScript进阶教程-4.dom零级 二级事件基础和实战

      本文链接:https://www.haomeiwen.com/subject/urfcqhtx.html