一、事件绑定方式
1.1 内联模式
在内联模型中,事件处理函数是 HTML 标签的一个属性,用于处理指定事件。虽然内联在早期使用较多,但它是和 HTML 混写的, 并没有与 HTML 分离。
//在 HTML 中把事件处理函数作为属性执行 JS 代码
<input type="button" value="按钮" onclick="alert('Lee');" />//注意单双引号
//在 HTML 中把事件处理函数作为属性执行 JS 函数
<input type="button" value="按钮"onclick="box();" />//执行 JS 的函数
PS:函数不得放到 window.onload 里面,这样就看不见了。
1.2 外联模式(脚本模式)
由于内联模型违反了 HTML 与 JavaScript 代码层次分离的原则。为了解决这个问题,我们可以在 JavaScript 中处理事件。这种处理方式就是脚本模型。
var input=document.getElementsByTagName('input')[0];//得到 input 对象
input.onclick=function(){//匿名函数执行
alert('Lee');
};
PS:通过匿名函数,可以直接触发对应的代码。也可以通过指定的函数名赋值的方式来执行函数(赋值的函数名不要跟着括号)。
input.onclick=box; //把函数名赋值给事件处理函数
二、事件处理函数
JavaScript 可以处理的事件类型为:鼠标事件、键盘事件、HTML 事件
PS:所有的事件处理函数都会都有两个部分组成,on+ 事件名称,例如 click 事件的事件处理函数就是:onclick。在这里,我们主要谈论脚本模型的方式来构建事件,违反分离原则的内联模式,我们忽略掉。
2.1 鼠标事件,页面所有元素都可触发
click:当用户单击鼠标按钮或按下回车键时触发
dblclick:当用户双击主鼠标按钮时触发。
mousedown:当用户按下了鼠标还未弹起时触发。
mouseup:当用户释放鼠标按钮时触发。
mouseover:当鼠标移到某个元素上方时触发。
mouseout:当鼠标移出某个元素上方时触发。
mousemove:当鼠标指针在元素上移动时触发。
mouseenter:当鼠标移到某个元素上方时触发。
mouseleave:当鼠标移出某个元素上方时触发。
PS: mouseover的子节点会重复触发,mouseenter则不会,mouseenter在IE8以后才有
2.2 键盘事件,表单元素或window触发
keydown:当用户按下键盘上任意键触发,如果按住不放,会重复触发。
οnkeydοwn=function(){
alert(‘Lee’);
};
keypress:当用户按下键盘上的字符键触发,如果按住不放,会重复触发
οnkeypress= function(){
alert(‘Lee’);
};
keyup:当用户释放键盘上的键触发。
οnkeyup=function() {
alert(‘Lee’);
};
2.3 HTML事件,表单元素或window触发
//load:当页面完全加载后在 window 上面触发,或当框架集加载完毕后在框架集上触发。
window.onload=function() { alert('Lee'); };
//unload:当页面完全卸载后在 window 上面触发,或当框架集卸载后在框架集上触发。
//只有IE浏览器兼容,当页面解构时触发(刷新页面或者关闭当前页面)
window.onunload= function(){ alert('Lee'); };
//resize:当窗口或框架的大小变化时在 window 或框架上触发。
window.onresize=function(){ alert('Lee'); };
//scroll:当用户滚动带滚动条的元素时触发。
window.onscroll=function() { alert('Lee'); };
//select:当用户选择文本框(input 或 textarea)中的一个或多个字符触发。
//当我们在输入框中选中文本的时候触发(光标选中input中的value值)
input.onselect=function(){ alert('Lee'); };
//change:当文本框(input 或 textarea)内容改变且失去焦点后触发。
//当我们修改了文本并且失去焦点时触发
input.onchange=function(){ alert('Lee'); };
//focus:当页面或者元素获得焦点时在 window 及相关元素上面触发。
input.onfocus= function(){ alert('Lee'); };
//blur:当页面或元素失去焦点时在 window 及相关元素上触发。
input.onblur=function(){ alert('Lee'); };
//submit:当用户点击提交type=submit按钮在<form>元素上触发。必须是form元素
form.onsubmit=function(){ alert('Lee'); };
//reset:当用户点击重置type=reset按钮在<form>元素上触发。必须是form元素
form.onreset=function(){ alert('Lee'); };
三、事件对象
3.1 事件对象
事件对象三部分组成:对象.事件处理函数=函数
//例如:单击文档任意处。
document.onclick=function(){
alert('Lee');
};
PS:以上程序的名词解释:click 表示一个事件类型,单击。onclick 表示一个事件处理 函数或绑定对象的属性(或者叫事件监听器、侦听器)。document 表示一个绑定的对象,用于触发某个元素区域。function()匿名函数是被执行的函数,用于触发后执行。
function box() {//普通空参函数
alert(arguments.length); //0,没有得到任何传递的参数
}
input.onclick=function(){//事件绑定的执行函数
alert(arguments.length); //1,得到一个隐藏参数
};
【注】通过上面两组函数中,我们发现,通过事件绑定的执行函数是可以得到一个隐藏参数的。
说明,浏览器会自动分配一个参数,这个参数其实就是 event 对象。
当我们点击按钮时,系统会自动调用事件绑定的函数,将事件对象当作函数的第一个参数传入。
input.onclick=function(){
alert(arguments[0]); //MouseEvent,鼠标事件对象
};//这种做法比较累,那么比较简单的做法是,直接通过接收参数来得到即可。
input.onclick=function(evt){
//接受 event 对象,名称不一定非要 event
alert(evt); //MouseEvent,鼠标事件对象
};
//事件对象的兼容性写法, 低版本IE(IE8)下使用 window.event。
input.onclick=function(evt){
var e = evt || window.event;
alert();
};
3.2 事件对象的属性
3.2.1 button属性
3.2.2 鼠标事件(可视区域及屏幕坐标)
可视区及屏幕坐标,事件对象提供了两组来获取浏览器坐标的属性,一组是页面可视区坐标,另一组是屏幕坐标
clientX clientY 可视窗口左上角为原点
screenX screenY 屏幕左上角为原点
pageX pageY 整个页面的左上角,包含滚出去的滚动距离
document.onclick=function(evt) {
alert(evt.clientX +','+evt.clientY);
alert(evt.screenX+','+evt.screenY);
};
区别
screenX: 鼠标位置相对于用户屏幕水平偏移量,而screenY也就是垂直方向的,此时的参照点也就是原点是屏幕的左上角。
clientX: 跟screenX相比就是将参照点改成了浏览器内容区域的左上角,该参照点会随之滚动条的移动而移动。
pageX:参照点也是浏览器内容区域的左上角,但它不会随着滚动条而变动。
3.2.3 鼠标事件(修改键)
有时,我们需要通过键盘上的某些键来配合鼠标来触发一些特殊的事件。这些键为: Shfit、Ctrl、Alt 和 Meat(Windows 中就是 Windows 键,苹果机中是 Cmd 键),它们经常被用 来修改鼠标事件和行为,所以叫修改键。
3.3 键盘事件
3.3.1 keyCode键码
在发生 keydown 和 keyup 事件时,event 对象的 keyCode 属性中会包含一个代码,与键盘上一个特定的键对应。对数字字母字符集,keyCode 属性的值与 ASCII 码中对应大写字母或数字的编码相同。字母中大小写不影响。
document.onkeydown=function(evt) {
alert(evt.keyCode); //按任意键,得到相应的 keyCode
};
3.3.2 charCode字符编码
Firefox、Chrome 和 Safari 的 event 对象都支持一个 charCode 属性,这个属性只有在发 生 keypress 事件时才包含值,而且这个值是按下的那个键所代表字符的 ASCII 编码。此时 的 keyCode 通常等于 0 或者也可能等于所按键的编码。
function getCharCode(evt) {
if(typeof evt.charCode== 'number') {
return evt.charCode;
}else{
return evt.keyCode;
}
}
PS:可以使用 String.fromCharCode()将 ASCII 编码转换成实际的字符。
3.4 触发事件的元素节点(target)
document.onclick=function(evt) {
alert(evt.target || window.event.srcElement);
};
四、事件冒泡和事件捕获
4.1 事件流
事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候, 那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围 的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。
4.2 事件冒泡
是从里往外逐个触发
4.3 事件捕获
是从外往里逐个触发。那么现代的浏览器默认情况下都是冒泡模式
4.4 阻止事件冒泡
事件冒泡会给我们的实际开发带来很多困扰,所以我们要阻止事件冒泡。
//阻止冒泡
cancelBubble=true stopPropagation()
五、阻止右键菜单
document.oncontextmenu = function(){
alert("右键被按下");
return false;
}//阻止官方的右键菜单
5.1 自定义右键菜单
//自定义右键菜单(HTML)
<body >
<div id="divId" style="width:300px;height:200px;background-color:red">
</div>
<div id="menuDiv" style="position:absolute;width:100px;height:80px;background-color:gray; ">
<ul >
<li>菜单1</li>
<li>菜单2</li>
<li>菜单3</li>
</ul>
</div>
</body>
//自定义右键菜单(JS)
document.oncontextmenu=function(){
return false;
}
document.getElementById("divId").onmousedown=function(){
if(event.button==2){
var menuDiv = document.getElementById("menuDiv");
menuDiv.style.left = event.clientX+"px";
menuDiv.style.top = event.clientY+"px";
menuDiv.style.display = "block";
}
}
document.body.onclick=function(){
document.getElementById("menuDiv").style.display = "none";
}
六、阻止超链接的默认行为
有时需要在a标签上添加click事件,并且跳转前处理一些事务,故需要做一些处理
function test(){
if(window.confirm("你确定要走么?")){
return true;
}else{
return false;
}
}
<body >
<a href="test.html" onclick="test()">走</a>
</body>
有时我们需要阻止事件的默认行为,比如:一个超链接的默认行为就点击然后跳转到指定的页面。那么阻止默认行为就可以屏蔽跳转的这种操作,而实现自定义操作。
取消事件默认行为还有一种不规范的做法,就是返回 false。
link.onclick = function () {
alert('Lee');
return false; //直接给个假,就不会跳转了。
};
PS:虽然 return false;可以实现这个功能,但有漏洞;
第一:必须写在最后,这样导致中间的代码执行后,有可能执行不到 return false;
第二:return false 写到最前那么之后的自定义操作就失效了。
所以,最好的方法应该是在最前面就阻止默认行为,并且后面还能执行代码。
七、拖拽原理
拖拽三剑客:相关的事件(onmousedown\onmousemove\onmouseup)
拖拽思路:
- 给目标元素添加onmousedown事件,拖拽的前提是在目标元素按下鼠标左键
记录鼠标按下的位置与目标元素的相对距离- 当onmousedown发生以后,此刻给document添加onmousemove事件,意味着此刻鼠标在网页的移动都将改变目标元素的位置
在onmousemove事件中,设定目标元素的left和top,公式。
目标元素的left = 鼠标的clientX – (鼠标和元素的横坐标差,即offsetX)
目标元素的top = 鼠标的clientY – (鼠标和元素的纵坐标差,即offsetY)- 当onmousedown发生以后,此刻给document添加onmouseup事件,意味着此刻鼠标在网页的任意位置松开鼠标,都会放弃拖拽的效果
- 获得浏览器的宽高:
windowWidth = document.documentElement.clientWidth || document.body.clientWidth
八、事件监听器
8.1 添加事件监听器
事件监听器:addEventListener() 方法用于向指定元素添加事件句柄,IE8及其以下不支持,火狐和谷歌支持。
事件监听器target.addEventListener(“click”, fun, false)
- “click” :是事件名;注意,要去掉事件名的on
- fun:是函数名; 注意,函数名上没有双引号
- 第三个参数是否使用捕捉(反向冒泡),默认false,为冒泡。
可以绑定多个函数在一个对象上,执行顺序按照绑定的顺序来
document.getElementById("myBtn1").addEventListener("click",myfun1,false);
当绑定的函数有参数时,当传递参数值时,使用"匿名函数"调用带参数的函数:
document.getElementById("myBtn").addEventListener("click", function() {
myFunction(p1, p2);
});
8.2 移除事件监听器
removeEventListener() 方法移除由 addEventListener() 方法添加的事件函数:
document.getElementById("myBtn1").removeEventListener("click",myfun1);
(1)如果对一个按钮重复添加点击事件,会进行覆盖,使用事件监听器不会覆盖,并且如果点击事件后又写了100行代码,想要给该按钮该事件继续添加功能,无需找到按钮对应的函数位置,直接添加事件监听器即可(因为事件监听器不会被覆盖,都可以执行)。
(2)如果一个事件上有多个函数,要删除某一事件的函数,传统事件绑定只会将事件由原来的函数设置为null,按钮上原本的点击事件也会被设置为null。使用事件监听器,可以移除指定的事件的函数。
(3)事件捕获:从外向里触发,事件冒泡:从里向外出发
1、传统事件绑定
<1>重复添加,覆盖
<2>不能精确的删除事件上的某一个函数
2、事件监听器(低版本IE浏览器下不兼容)
addEventListener()
格式:node.addEventListener("click")
参数:
第一个参数 事件类型
第二个参数 绑定函数
第三个参数 布尔值 true 事件捕获
false 事件冒泡 默认
removeEventListener()
格式:node.removeEventListener
参数:
第一个参数 事件类型
第二个参数 删除函数名字
8.3 事件监听器兼容
IE 实现了与 DOM 中类似的两个方法:attachEvent()和 detachEvent()。这两个方法接受相同的参数:事件名称和函数
//跨浏览器添加事件
function addEvent(obj, type, fn) {//btn,click,show
if (obj.addEventListener) {
obj.addEventListener(type, fn, false);
} else if (obj.attachEvent) {
obj.attachEvent('on' + type, fn);
}
}
//跨浏览器移除事件
function removeEvent(obj, type, fn) {
if (obj.removeEventListener) {
obj.removeEventListener(type, fn, false);
} else if (obj.detachEvent) {
obj.detachEvent('on' + type, fn);
}
}
九、事件委托
onclick,onmouseover,onmouseout等是事件,委托就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。
也就是:利用冒泡的原理,把事件加到父级上,触发执行效果。
事件委托最强王者法则:
- 找到当前要添加事件的元素节点的父级或者祖父节点
- 将事件绑定在父一级的标签
- 找出触发该事件的对象(target,不能用this),进行判断
var oUl = document.getElementById("ul1");
oUl.onclick = function(ev){
var e = ev || window.event;
var target = e.target || window.event.srcElement;
if(target.nodeName.toLowerCase() == "li"){
target.style.backgroundColor = 'red';
}
}
var obtn = document.getElementById("btn1");
var i = 6;
obtn.onclick = function(){
var newNode = document.createElement("li");
newNode.innerHTML = i++ * 1111;
oUl.appendChild(newNode);
}