事件处理函数
1、ele.onxxx = function(event) {}
兼容性很好,但是一个元素的同一个事件上只能绑定一个处理程序
等同于写在行间上: <div onclick="console.log('a')"></div>
程序 this 指向 dom 元素本身
2、obj.addEventListener(type, fn, false)
IE9以下不兼容,可以为一个事件绑定多个处理程序
div.addEventListener(type, function() {}, false)
div.addEventListener(type, function() {}, false)
两个函数不能是同一个函数
程序 this 指向 dom 元素本身
3、obj.attachEvent('on' + type, fn)
IE 独有,一个事件绑定多个处理程序
div.attachEvent(type, function() {})
div.attachEvent(type, function() {})
两个函数可以是是同一个函数
程序 this 指向 window
4、封装兼容的 添加事件函数
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); //解决 attachEvent this指向window的问题 }) } else { elem['on' + type] = handle; } }
5、练习:用addEventListener 给每一个li添加事件,点击返回li 的顺序
<ul> <li>a</li> <li>a</li> <li>a</li> <li>a</li> </ul> <script type="text/javascript"> var li = document.getElementsByTagName('li'), len = li.length; for(var i = 0; i < len; i ++) { (function (i) { //这里形成了闭包,因此需要用立即执行函数 li[i].addEventListener('click', function() { console.log(i + 1); }, false); }(i)); } </script>
解除事件处理程序
1、ele.onclick = false // null
div.onclick = function () {
console.log('1');
this.onclick = null;
}
2、ele.removeEventListener(type, fn, false);
div.addEventListener('click', handle, false);
function handle() {console.log('a');}
div.removeEventListener('click', handle, false);
3、ele.detachEvent('on' + type, fn);
注意:如果绑定 匿名函数, 则无法解除
事件处理模型
1、事件冒泡:
结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,
即同一事件,自子元素冒泡向父元素。 (自底向上)
例: <div class="wrapper"> <div class="content"> <div class="box"> </div> </div> </div> <script type="text/javascript"> var wrapper = document.getElementsByClassName('wrapper')[0], content = document.getElementsByClassName('content')[0], 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); </script>
点击wrapper 时, 打印 wrapper
点击content时, 打印 content wrapper
点击box时, 打印 box content wrapper
2、事件捕获
结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,
即同一事件,自父元素冒泡向子元素(事件源元素)。 (自顶向下)
IE没有捕获事件
例: <div class="wrapper"> <div class="content"> <div class="box"> </div> </div> </div> <script type="text/javascript"> var wrapper = document.getElementsByClassName('wrapper')[0], content = document.getElementsByClassName('content')[0], box = document.getElementsByClassName('box')[0]; wrapper.addEventListener('click', function() { console.log('wrapper'); }, true); //改为true,就变成了捕获 content.addEventListener('click', function() { console.log('content'); }, true); box.addEventListener('click', function() { console.log('box'); }, true); </script>
点击wrapper 时, 打印 wrapper 点击content时, 打印 wrapper content 点击box时, 打印 wrapper content box
3、触发顺序,先捕获,后冒泡,被点击区域,按照事件执行顺序执行
4、focus, blur, change, submit, reset, select 等事件不冒泡
5、取消冒泡:
1、W3C标准 event.stopPropagation(); 但不支持ie9以下版本
2、IE独有 event.cancelBubble = true;
3、封装取消冒泡函数:
function stopBubble(event) { if(event.stopPropagation) { event.stopPropagation(); }else { event.stopBubble = true; } }
阻止默认事件
默认事件有 : 表单提交, a 标签跳转, 右键菜单 等
1、return false : 以对象属性的方式注册的事件才生效,
如:(1)a 标签
a 标签跳转会重新加载页面和跳到页面顶端
a 标签href 里可以写javascript 代码,如
<a href = "javascript:alert(‘a’)">demo</a>
a标签取消默认事件:<a href = "javascript:void(false)">demo</a>
(2)右键菜单: document.oncontextmenu = function () {
console.log('a');
return false;
}
2、event.preventDefault() : IE9以下不兼容,
例: 右键菜单: document.oncontextmenu = function (e) {
console.log('a');
e.preventDefault();
· }
3、event.returnValue = false; 兼容IE
例: 右键菜单: document.oncontextmenu = function (e) {
console.log('a');
e.returnValue = false;
}
4、封装阻止默认事件的函数
function cancelHandler(event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } }
事件对象
event || window.event(用于IE)
1、事件源对象 target
event.target 火狐只有这个
event.srcElement ie只有这个
chrome 两个都有
兼容性写法:
div.onclick = function (e) {
var event = e || window.event;
var target = event.target || event.srcElement;
}
例子:3000个li,点击相应的li ,输出相应li 的文本
var ul = document.getElementsByTagName(‘ul’)[0]; // 先获取ul ,因为每个li 事件都会冒泡到ul ul.onclick = function (e) { var event = e || window.event; var target = event.target || event.srcElement; console.log(target.innerHTML); }
事件委托
利用事件冒泡,和事件源对象进行处理
优点:
1、性能不需要循环所有的元素一个个绑定事件
2、灵活 当有新的子元素时不需要重新绑定事件
鼠标事件
1、鼠标事件有:click mousedown mousemove mouseup contextmenu
mouseover-mouseout == mouseenter -mouseleave
click == mousedown + mouseup
2、用button 来区分鼠标的按键 0 / 1 /2
左键:0 中键:1 右键: 2
3、DOM3 标准规定:click事件只能监听左键,只能通过mousedown和 mouseup 来判断鼠标键
4、如何解决mousedown 和 click 的冲突
var firstTime = 0, lastTime = 0, key = false; document.onmousedown = function() { firstTime = new Date().getTime(); } document.onmouseup = function() { lastTime = new Date().getTime(); if(lastTime - firstTime < 300) { key = true; } } document.onclick = function() { if(key) { console.log('click'); key = false; } }
5、例子:拖拽
<div style="width: 80px;height: 80px;background-color: red;"></div> <script type="text/javascript"> var div = document.getElementsByTagName('div')[0]; div.onmousedown = function() { div.onmousemove = function() { var event = e || window.event; div.style.left = e.pageX + 'px'; } } </script>
6、div.setCapture(); 事件捕获,仅在IE里好使,div会捕获页面上发生的所有事件到自己身上
div.releaseCapture();
键盘事件
1、keydown keyup keypress
2、keydown > keypress > keyup:顺序是先keydown ,keypress 到 keyup
3、keydown 和 keypress 的区别:
keydown 可以响应任意键盘按键, charCode:0
keypress只可以响应字符类键盘按键 charCode 10
keypress返回ASCII码, 可以转换成相应字符
4、打印键盘对应的字符
document.onkeypress = function(e) {
console.log(String.fromCharCode(e.charCode));
}
文本操作事件:
1、input
var input = document.getElementsByTagName('input')[0]; input.oninput = function (e) { console.log(this.value); } //但凡input 里的内容有变化,都会打印input里的内容
2、change
var input = document.getElementsByTagName('input')[0]; input.onchange = function (e) { console.log(this.value); } //当input 里失去焦点,就会打印input里的内容
3、focus,blur
input默认值的设置
<input type="text" value="请输入用户名" onfocus="if(this.value == '请输入用户名')this.value=''" onblur="if(this.value=='')this.value='请输入用户名'"/>
窗体操作类 --> window上的事件
1、scroll :scoll滚动条一滚动,事件触发:
2、load : window.onload = function(){}
浏览器执行顺序:
先生成一个domTree , cssTree,两个合成一个渲染树 renderTree
onload 会等整个文档解析完后,renderTree 构建完后,dom所有的信息全部下载完后,
整个页面全部就绪的时候,才会触发load事件,这个效率是最低的
4、例子:fixed 定位 js兼容版
function positionFixed(elem) { var elemTop = elem.offsetTop; window.onscroll = function() { div.style.top = window.pageYOffset + elemTop + 'px'; } }