-
Js中的事件:
Onsubmit:用于表单提交之前,验证所有表单。
Onload和onunload用户进入或离开时触发,可用于处理cookie
Onload主要用于Body标签:页面一加载就触发
Onmouseenter ,onmouseover,onmouseleave等为鼠标事件
表单事件:表单元素事件,在表单元素中才有效
onchange 框内容改变时
onsubmit 点击提交按钮时
onreset 重新点击鼠标按键时
onselect 文本被选择时
onblur 元素失去焦点时
onfocus 当元素获取焦点时
键盘事件:onkeydown, onkeyup, onkeypress
鼠标事件:
onclick 鼠标点击一个对象时
ondblclick 鼠标双击一个对象时
onmousedown 鼠标被按下时
onmousemove 鼠标被移动时
onmouseout 鼠标离开元素时
onmouseover 鼠标经过元素时
onmouseup 释放鼠标按键时
2.Js中的事件绑定机制:
①行内支持以on开头的onclick,onblur等以on开头的【不能实现事件重复绑定】
<button onclick="var i=1;alert(i)">弹出</button>
②当代码较多时,在onclick中指定函数名。【不能实现事件重复绑定】
<div id="box" onclick="func()"></div>
③在js代码中通过dom元素onclick等属性【不能实现事件重复绑定】
var b=document.getElementById('box');
b.onclick=function(){
b.style.backgroundColor ='blue';
}
④使用W3C标准的addEventListener和removeEventListener。
type:事件类型,不含"on",比如"click"、"mouseover"、"keydown";
// listener:事件处理函数
// useCapture是事件冒泡,默认false:事件冒泡(由向校外),反之true
addEventListener(type, listener, useCapture);
var btn=document.getElementsByTagName('button')[0];
btn.addEventListener('click',function(){
alert(2)
})
a) 事件处理函数中this代表的是dom对象,不是window,这个特性与attachEvent不同。
b) 同一个事件处理函数可以绑定2次,一次用于事件捕获,一次用于事件冒泡。
但如果绑定同一个事件处理函数并且同为true/false,则只触发一次。
3.事件的执行顺序:
捕获阶段的处理函数最先执行,其次是目标阶段的处理函数,最后是冒泡阶段的处理函数。目标阶段的处理函数,先注册的先执行,后注册的后执行。
4.事件冒泡(由内向外) 事件捕获(由外向内)
5.Dom事件流:三个阶段(捕获阶段,目标阶段,冒泡阶段)
先调用捕获阶段的处理函数,再调用目标阶段处理函数,再调用冒泡阶段的处理函数。
hml代码:
<div id="outA" style="width: 400px;height: 400px;position: relative;background-color: #080aff">
<div id="outB" style="width: 400px;height: 400px;position: relative;top: 50px;background-color: #99ffde">
<div id="outC" style="width: 400px;height: 400px;position: relative;top: 50px;background-color: #b24dff"></div>
</div>
</div>
js代码:
<script>
outC.addEventListener('click',function(){console.log('target');},true);
//冒泡
outA.addEventListener('click',function(){console.log('bubble1')},false);
outB.addEventListener('click',function(){console.log('bubble2')},false);
//捕获
outA.addEventListener('click',function(){console.log('capture1')},true);
outB.addEventListener('click',function(){console.log('capture2');},true);
</script>
//结果:capture1,capture2-->target-->bubble1,bubble2
6.阻止事件冒泡:
outC.addEventListener('click',function(e){console.log('target');
e.stopPropagation();
},true);
outA.addEventListener('click',function(){console.log('bubble1')},false);
outA.addEventListener('click',function(){console.log('capture1')},true);
//capture1-->target target之后的被阻止
7.事件委托机制:
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
经典例子:
有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
这里包含两层意思:
1.现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;
2.新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。
为什么要用事件委托机制?
在javascript中,页面中的事件处理程序越多,其与dom元素交互的次数多,访问dom的次数就越频繁,引起了浏览器页面的重绘重排越多,从加长了网页的交互时间。也是提升网页性能之一:减少dom的访问次数。(如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;)
事件委托栗子1:
<ul id="ull">
<li>第一个</li>
<li>第二个</li>
<li>第三个</li>
</ul>
<script>
var ull=document.getElementById('ull')
ull.onclick=function(){
console.log(123)
}//将li的时间委托给ul(事件冒泡:由内而外触发)
</script>
栗子2:
<input type="button" value="click me" id="btn6">
<script>
//event提供了一个事件属性target,可以返回目标事件节点,成为事件源
//即target可以代表当前的dom,但不是真正的dom
var btn6=document.getElementById('btn6');
document.onclick=function(e){
e=e|| window.e;
var target= e.target|| e.srcElement;//标准浏览器用ev.target,IE浏览器用event.srcElement,
if(target==btn6){
alert(target.value)
}
}
</script>
栗子3:
鼠标点击li标签:添加背景色,点击按钮:添加新元素
<input type="button" value="添加" id="btn">
<ul id="ulist">
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
//(1)常规写法:
var btn=document.getElementById('btn');
var ulist=document.getElementById('ulist');
var lii=document.getElementsByTagName('li');
var num=3;
function func(){
for(var i=0;i<lii.length;i++){
lii[i].onclick=function(){
this.style.backgroundColor='red';
}
}
}
func();
btn.onclick=function(){
num++;
var lis=document.createElement('li');
lis.innerHTML=111*num;
ulist.appendChild(lis);
func();
}
//虽然实现了会发现dom的访问次数很多,明显不利于提高网页性能。
//(2)事件委托写法
用事件委托的方法,新添加的元素是带事件的。可以看出事件委托不用for循环遍历li标签,只需对ul设置方法,都可在js代码中执行,大大减少了dom的操作
var btn=document.getElementById('btn');
var ulist=document.getElementById('ulist');
var lii=document.getElementsByTagName('li');
var num=3;
ulist.onclick=function (e){
var e=e|| window.e;
var target= e.srcElement|| e.target;
//元素标签:用nodeName来获取具体是什么标签名,这个返回的是一个大写的,我们需要转成小写再做比较
//属性名称则不用转直接target.id等
if(target.nodeName.toLowerCase() == 'li'){
target.style.backgroundColor='blue';
}
}
btn.onclick=function(){
num++;
var lis=document.createElement('li');
lis.innerHTML=111*num;
ulist.appendChild(lis);
}
适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
事件委托优点:
减少事件注册,节省内存。
减少dom的操作,提高js代码的运行速度。
事件委托缺点:
事件委托基于冒泡,对于不冒泡的事件不支持。
层级过多,冒泡过程中,可能会被某层阻止掉。
理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。