交互体验的核心功能
演示demo——拖拽,和点击
一.如何绑定事件处理函数
- ele.onxxx = function (event){}
eg: div.onclick = function(){}
- 兼容性很好,但是一个元素的同一个事件只能绑定一个处理程序
- 基本等同于写在html行间上
- obj.addEventListener(事件类型type, 处理函数fn, false);
eg:点击事件
obj.addEventListener('click', function(){
console.log('a');
}, false);
*IE9以下不兼容,可以为一个事件绑定多个处理程序 - obj.attachEvent('on'+事件类型type, 处理函数fn);
eg: div.attachEvent('onclick', function(){});
- IE独有,一个事件同样可以绑定多个处理程序
二.事件处理程序的运行环境
- ele.onxxx = function (event){}
程序this指向是dom元素本身 - obj.addEventListener(type, fn, false);
程序this指向是dom元素本身 - obj.attachEvent('on'+type, fn);
程序this指向window
如何将this修改为指向dom元素本身呢?
div.attachEvent('onclick', function(){
handle.call(div);//会指向div
});
function handle(){
this.xxx = xxx;
}
- 封装兼容性的addEvent(elem, type, handle);方法
//封装兼容性的事件处理函数,给一个dom元素添加该事件类型的处理函数
function addEvent(elem, type, handle) {
if(elem.addEventListener){
elem.addEventListener(type, handle, false);
}else if(elem.attachEvent){
elem.attachEvent('on'+ type, function() {
handle.call(elem);
})
}else{
elem['on'+ type] = handle;
}
}
三.解除事件处理程序
- ele.onclick = false/''/null;
- ele.removeEventListener(type, fn, false);
div.addEventListener('click',test,false);
function test() {
console.log('a');
}
div.removeEventListener('click', test, false);
当处理函数完全一致时(地址指向一致)才可解除
- ele.detachEvent('on' + type, fn);
- 注:若绑定匿名函数,则无法解除
四.事件处理模型——事件冒泡、捕获
事件处理模型:系统或元素针对事件的处理方式
注意:一个对象的一个事件类型上面绑定的一个处理函数,只能遵循一种事件模型
- 事件冒泡:
- 结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
- 事件捕获:
- 结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
- obj.addEventListener(事件类型type, 处理函数fn, true);
IE没有捕获事件
- 触发顺序,先捕获,后冒泡
一个对象的一个事件类型绑定两个处理函数,一个遵循事件捕获,一个遵循事件冒泡。触发顺序是,先捕获,后冒泡 - focus, blur, change, submit, reset, select等事件不冒泡
五.取消冒泡和阻止默认事件
- 取消冒泡:
- W3C标准event.stopPropagation();但不支持ie9以下版本
(1)事件对象:在每个事件处理函数上面可以写一个形参,系统会帮助传这个形参即事件对象,事件对象上面有很多属性,属性记载了事件发生时的一系列数据和信息,以供使用。
(2) event.stopPropagation()为事件对象e上的一个属性
eg:
document.onclick = function(){
console.log('xxx');
}
var div = document.getElementByTagName('div');
div.onclick = function(e) {
//e即为事件对象
e.stopPropagation();
this.style.background = "green";
//如果没有上面一行的取消冒泡操作,
//点击div时背景既会变成绿色,也会打印console.log中的内容。
//(因为他是整个页面上的点击事件内容)
}
- IE独有 event.cancelBubble = true;
- 封装取消冒泡的函数stopBubble(event)
- 阻止默认事件:
- 默认事件——表单提交,a标签跳转,右键菜单等
(1)return false;以对象属性的方式注册的事件才生效
阻止右键弹出菜单
document.oncontextmenu = function() {
console.log('a');
return false;
}
(2)event.preventDefault();W3C标准,IE9以下不兼容
document.oncontextmenu = function(e) {
e.preventDefault();
console.log('a');
}
(3)event.returnValue = false;兼容IE
(4)封装阻止默认事件的函数cancelHandler(event);
function cancelHandler(event){
if(event.preventDefault()){
event.preventDefault();
}else{
event.returnValue = false;
}
}
- a标签跳转默认跳到页面的开头,如何去掉这个默认事件呢?
//html
<a href = "#">www.xxx.com</a>
//javascript
var a = document.getElementsByTagName('a')[0];
a.onclick = function(e) {
cancelHandler(e);//利用上方的阻止默认事件的封装函数
}
或,行间中写javascript,冒号后的东西相当于return。
<a href = "javascript:void(false)">www.xxx.com</a>
六.事件对象
- event || window.event用于IE
- 事件源对象:事件对象上的属性,是事件触发的源头
- event.target 火狐只有这个
- event.srcElement IE只有这个
- 这俩chrome都有
//html
<div class = "wrapper">
<div class = "box"></div>
</div>
//js
var wrapper = document.getElementsByClassName('wrapper');
var box = document.getElementsByClassName('box');
wrapper.onclick = function(e){
var event = e || window.event;//event为事件对象
var target = event.target || event.srcElement;//事件源对象
console.log(target);//此时点击box区域,会打印box,即此点击事件触发的源头
}
- 兼容性写法
七.事件委托
- 利用事件冒泡,和事件源对象进行处理
- 优点:
(1)性能 不需要循环所有的元素一个个绑定事件
(2)灵活 当有新的子元素时不需要重新绑定事件
eg:点击任意li,输出相应的数字内容。
//html
<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>
</ul>
//js
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function (e) {
//li在ul内部,点击li部分时,会逐步冒泡给ul
var event = e || window.event;//事件对象
var target = event.target || event.srcElement;//事件源对象
console.log(target.innerText);
}
比for循环性能更好,事件没有绑定在li上