# 事件处理函数

如何绑定事件处理函数?

***1.***ele.onxxx = function(event){} 兼容性很好,但是一个元素的同一个事件上只能绑定一个事件,基本上等同于写在HTML行间上 <div style="width:100px;" onclick="consloe.log('a')"></div>

<div style="width:100px;height:100px;background-color:red;"></div>
1
var div = document.getElementsByTagName('div')[0];
    div.onclick = function() {
        this.style.backgroundColor = 'green';
    }
1
2
3
4

2.obj.addEventListener(事件类型,处理函数,fasle) IE9以下不兼容,可以为一个事件绑定多个处理程序,并且按照绑定的顺序来执行

    div.addEventListener('click',function(){
            console.log('a');
        },false);        
    div.addEventListener('click',function(){
            console.log('b');
        },false);
1
2
3
4
5
6

3.obj.attachEvent('on'+事件类型,处理函数); IE独有,一个事件同样可以绑定多个处理程序

    div.attachEvent('onclick',function(){
            console.log('a');
    });
1
2
3

小提示

绑定事件的处理函数里面如果用到for循环里面的i,就要考虑下是否是闭包的问题

事件处理函数的运行环境

ele.onxxx和obj.addEventListener程序this指向的是dom元素本身

obj.attachEvent程序this指向window

# 小练习

<div class="container">
        <p>
            <button id="btnClear">清空</button>
        </p>
        <ul class="list">
            <li>项目1<button>删除</button></li>
            <li>项目2<button>删除</button></li>
            <li>项目3<button>删除</button></li>
            <li>项目4<button>删除</button></li>
            <li>项目5<button>删除</button></li>
            <li>项目6<button>删除</button></li>
            <li>项目7<button>删除</button></li>
            <li>项目8<button>删除</button></li>
            <li>项目9<button>删除</button></li>
            <li>项目10<button>删除</button></li>
        </ul>
    </div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var btnclear = document.getElementById("btnClear");
        var ul = document.querySelector(".list");

        btnclear.onclick = function() {
            ul.innerHTML = "";
        }
        //得到ul下的所有按钮
        var btns = ul.querySelectorAll("button");
        for (var i = 0; i < btns.length; i++){
            var b = btns[i];  //得到当前按钮
            b.onclick = function() {
                this.parentNode.remove();
            }
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 封装函数

封装兼容性的addEvent(elem,type,handle);方法,三个参数,一个元素,一个事件类型,一个处理函数

function addEvent(elem,type,handle) {
    if(elem.addEventListener) {
        elem.addEventListener(type,handle,fasle);
    }else if(elem.attachEvent) {
        elem,attachEvent('on'+type,function(){
            handle.call(elem);
        })
    }else{
        elem['on'+type] = handle;
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 解除事件处理程序

elel.onclick = false/null;
ele.removeEventListener(type,fn,false);
ele.detachEvent('on'+type,fn);
//若绑定匿名函数,则无法解除
1
2
3
4
var div = document.getElementsByTagName('div')[0];
    div.onclick = function() {
        console.log('a');
        this.onclick = null;
    }
1
2
3
4
5
var div = document.getElementsByTagName('div')[0];
    div.addEventListener('click',test,false);
        function test(){
            console.log('a');
        }
    div.removeEventListener('click',test,false);
1
2
3
4
5
6

# 事件处理模型

# 事件冒泡

<div class="wrapper">
    <div class="content">
        <div class="box"></div>
    </div>
</div>
1
2
3
4
5
.wrapper {
        width: 400px;
        height: 400px;
        background-color: red;
    }
.content {
        width: 300px;
        height: 300px;
        background-color: green;
    }
.box {
        width: 200px;
        height: 200px;
        background-color: blue;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var wrapper = document.getElementsByClassName('wrapper')[0];
var content = document.getElementsByClassName('content')[0];
var box = document.getElementsByClassName('box')[0];

wrapper.addEventListener('click',function(){
    console.log('wrapper')
},false);
content.addEventListener('click',function(){
    console.log('content')
},false);
box.addEventListener('click',function(){
    console.log('box')
},false);
1
2
3
4
5
6
7
8
9
10
11
12
13

事件冒泡

结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素(从代码的角度上自底向上冒泡)

点击蓝色区域会自底向上冒泡

# 事件捕获

事件捕获

结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)(自顶向下)

依次点击蓝色绿色红色,捕获正好和冒泡相反,触发捕获就是给addEventListener的第三个参数填true即可触发

IE没有捕获事件

事件冒泡和捕获

触发顺序,先捕获,后冒泡

事件捕获跟事件冒泡正好传递顺序相反,想要触发事件捕获,把里面的false该位true就可以,同一个对象只能绑定一个事件类型

focus,blur,change,submit,reset,select等事件不冒泡

同一个对象的同一个事件类型,上面绑定了两个处理函数,一个冒泡,一个捕获

wrapper.addEventListener('click',function(){
    console.log('wrapperBubble')
},false);
content.addEventListener('click',function(){
    console.log('contentBubble')
},false);
box.addEventListener('click',function(){
    console.log('boxBubble')
},false);
wrapper.addEventListener('click',function(){
    console.log('wrapper')
},true);
content.addEventListener('click',function(){
    console.log('content')
},true);
box.addEventListener('click',function(){
    console.log('box')
},true);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

事件执行一定要按照顺序来,因为是boxBubble先绑定的,所以就先执行boxBubble,如果把整个三个捕获放在前面,等到蓝色区域(box)执行的时候就先打印box,再打印boxBubble.

# 阻止冒泡

document.onclick = function (){
    console.log('你闲的呀');
}
div.conclick = function(e) {
    this.style.backgroundColor = 'green';
    // e.stopPropagation();
    //此时的e就是系统的事件对象
    e.cancelBubble = true;
    //IE的
}
//W3C标准event.stopPropagation(),但不支持IE9以下版本
//IE独有event.cancelBubble = true;
1
2
3
4
5
6
7
8
9
10
11
12

# 封装函数

封装取消冒泡的函数

function stopBubble(event) {
    if(event.stopPropagation) {
        event.stopPropagation();
    }else{
        event.cancelBubble = true;
    }
}
    stopBubble(e);
1
2
3
4
5
6
7
8

# 阻止默认事件

默认事件

表单提交,a标签跳转,右键菜单等等

# 1.return false; 以对象属性的方式注册的事件才生效

    document.oncontextmenu = function () {
        console.log('a');
        return false;//禁止右键菜单呼出
    }
1
2
3
4

# 2.event.preventDefault();w3c标注,ie9以下不兼容

    document.oncontextmenu = function (e) {
    console.log('a');
    e.preventDefault();//禁止右键菜单呼出
}
1
2
3
4

# 3.event.returnValue = false;兼容IE

    document.oncontextmenu = function (e) {
    console.log('a');
    e.returnValue = false;//禁止右键菜单呼出
}
1
2
3
4

# 封装函数

封装阻止默认事件的函数cancelHandler(event)

document.oncontextmenu = function(e) {
    console.log('a');
    cancelHandler(e);
}
function canceHandler(event) {
    if(event.preventDefault) {
        event.preventDefault();
    }else{
        event.returnValue = false;
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 事件对象

event谷歌||window.event用于IE

# 事件源对象

event.target 火狐只有这个 event.srcElement IE只有这个 chrome上面包含了这两个.

# 封装函数

div.onclick = function(e) {
    var event = e || window.event;
    var target = even.target || event.srcElement;
    console.log(target);
}
1
2
3
4
5

# 事件委托

事件委托

利用事件冒泡,和事件源对象进行处理

优点:1.性能 不需要循环所有的元素一个个绑定事件

2.灵活 当有新的子元素时不需要重新绑定事件

事件委托例子(打印ul里面的li里面的文本内容)

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
var li = document.getElementsByTagName('li');
        var len = li.length;
        for (var i = 0; i < len; i ++){
            li[i].onclick = function(){
                console.log(this.innerText);
            }
        }
1
2
3
4
5
6
7

如果li多了,给每个li绑定事件,这样效率会很低,所以建议用事件委托

var ul = document.getElementsByTagName('ul')[0];
    ul.onclick = function(e) {
        var event = e || window.event;
        var target = event.target || event.srcElement;
        console.log(target.innerText);
        //因为ul里面li的源对象就是它自己,所以打印自己的文本内容
}
1
2
3
4
5
6
7

# 事件分类

# 鼠标事件

click,mousedown,mousemove,mouseup``,contextmenu,mouseover,mouseout,mouseenter,mouseleave

click = mousedown+mouseup 三个事件同时在页面上执行顺序是mousedown,mouseup,click mousemove 鼠标移动事件 contextmenu 鼠标右键唯一的用途就是禁止鼠标右键事件 mouseover 当鼠标移入该区域发生函数样式 mouseout 当鼠标移出该区域发生函数样式 mouseenter,mouseleavemouseover,mouseout功能和写法都一样,都是H5的新语法

Dom3标准规定

click事件只能监听左键,只能通过mousedown和mouseup来判断鼠标键

# 例子

用事件对象button来区分鼠标的按键,0/1/2

document.onmousedown = function(e) {
    if(e.button == 2) {
            console.log('right');
        }else if(e.button == 0) {
            console.log('left');
        }
    }
1
2
3
4
5
6
7
<div style="width: 100px;height: 100px;background-color: red;position: absolute;left:0;top:0;"></div>
1
var div = document.getElementsByTagName('div')[0];
var disX,
    disY;
div.onmousedown = function(e) {
    disX = e.pageX - parseInt(div.style.left);
    disY = e.pageY - parseInt(div.style.top);

document.onmousemove = function(e) {
        var event = e|| window.event;
            div.style.left = e.pageX - disX + "px";
            div.style.top = e.pageY - disY + "px";
        }
document.onmouseup = function() {
            div.onmousemove = null;
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

typeof 的几个特例

div.setCapture捕获页面上发生的所有事件,在任意地方发生的任何事件都加到自己身上

div.releaseCapture()快用完的时候释放掉

# 键盘事件

keydown keyup keypress 触发顺序 keydown>keypress>keyup

keydown和keypress的区别

keydowncharCode = 0;

keydown可以响应所有键盘按键, keypress只可响应字符类键盘按键

keypress返回ascll码,可以转换为对应字符

document.onkeypress = function(e) {
    console.log(String.fromCharCode(e.charCode));
    //返回按下的相应按键
}
1
2
3
4

# 文本操作事件

input

var input = document.getElementsByTagName('input')[0];
    input.oninput = function (e) {
    console.log(this.value);
//在输入框无论输入什么值都会在控制台上从左到右打印
//删除一个值也会在控制台从左到右打印
}
1
2
3
4
5
6

focus,blur <input type="text" value="请输入用户名"style="color:#999" onfocus="if(this.value=='请输入用户名'){this.value='';this.style.color='#424242'}" onblur="if(this.value==''){this.value='请输入用户名';this.style.color='#999'}">


change 鼠标聚焦到输入框上,输入字符不发生改变,鼠标离开输入框发生改变

# window上的事件

窗口操作类事件

scroll 滚动条滚动的位置

load 整个页面图片等解析完毕后window触发onload事件才执行函数,效率最低

window.onload = function() {
var div = document.getElementsByTagName('div')[0];
    console.log(div);
    div.style.width = "100px";
    div.style.height = "100px";
    div.style.backgroundColor = "red";
1
2
3
4
5
6

# 二维数组

扫雷游戏会用到二维数组

    var arr = [
        [1  ,2  ,3],
        [11 ,22 ,33],
        [111,222,333]
        ]
              
        arr[0][0];//第一行的第一个
        arr[1][0];//第二行的第一个
1
2
3
4
5
6
7
8