事件入门
什么是事件
事件是由用户和浏览器进行交互的操作
三种事件模型内联模型
内联事件模型
作为html标签的一个属性存在的,但是这种模型已经不适合在大的项目中使用。onclick
脚本模型
但是注意的是:如果这段脚本是对整个DOM进行操作的话,必须是在DOM加载完才执行这个脚本,让事件处理函数(onclick)执行一个函数的时候,通过赋值的方式,直接将函数名赋值给事件处理函数即可,而不是为这个事件处理函数赋值为函数() 如果有括号的话会自己调用,而不是等待事件来触发
DOM2级模型
事件处理函数
onclick等事件
onkeydown 事件 按下键盘上的任意的按钮都可以输出111
onkeydown=function(){
console.log(111);
}
onkeypress 事件 按下键盘上的字母键或者是数字键才可以触发这个事件,按下shift ctrl键都没有用
onkeypress=function(){
console.log(111);
}
onkeyup 事件在按下键盘并释放键盘的时候才会触发这个事件
onkeyup=function(){
console.log(111);
}
onunload 事件 在页面真个卸载的时候,才触发 比如说刷新的时候
onselect 事件 选择文本输入框的内容 释放的时候会触发这个事件
cc.onselect=function(){
console.log(11);
}
onchange 事件 文本框内改变内容并且失去焦点的时候触发
form上边的事件 这些表单必须在一个form里边
submit没有form是提交不了的,而且不是在input上边触发的,而是在form上边触发的
onresize事件 window 的事件 改变窗口的大小会触发的事件
onscroll事件 window 的事件 滚动窗体的时候会触发的事件
事件对象
事件处理的三个部分
1、DOM 2、事件处理函数 3、事件处理方法
事件对象
当触发一个事件的时候就会产生一个事件对象 浏览器通过函数把这个对象作为参数传递过来,event,所以这个对象会存在非常多的兼容性(就连得到这个对象的方式)
window.onload=function(){
var box=document.getElementById("box");
box.onclick=function(){
console.log(arguments.length) //点击的时候会传递一个事件对象 所以这里会输出1
}
}
所以下面的代码也可以
var box=document.getElementById("box");
box.onclick=function(e){
console.log(e) //得到的就是事件对象
}
值得注意的是,IE中都不支持这种方式来得到事件对象,上面的方式是W3C获取事件对象的方式,在IE下可以通过window的属性直接来获取
下面的代码实现了获取事件对象的兼容
box.onclick=function(e){
var event=window.event||e;
alert(event) //得到的就是事件对象
}
鼠标事件对象跨浏览器来获得用户按下是左键?中键?右键?
window.onload=function() {
var box = document.getElementById("box");
document.onmouseup=function(e){
var event=e||window.event;
alert(getButton(e));
}
}
function getButton(event){
if(event){
return event.button;
}
else if(window.event){
switch(window.event.button){
case 1: return 0;
case 4: return 1;
case 2: return 2;
}
}
}
跨浏览器获得鼠标点击位置在视窗的位置(不管你是放大了浏览器还是有了滚动条,都是看的是鼠标的点击的位置离视窗的位置),而且这个程序还可以输出有滚动条的时候,滚动条的离顶部的位置
document.onmouseup=function(e){
var event=window.event||e;
alert(document.documentElement.scrollTop||document.body.scrollTop+"px"+event.clientX+"px"+ event.clientY+"px");
}
值得注意的是:获得滚动条离最顶部的距离的时候的兼容的情况
下面这个程序是获得了鼠标点击的位置离屏幕的距离
document.onmouseup=function(e){
var event=window.event||e;
alert(event.screenX+"px"+" "+event.screenY+"px");
}
注意:只能为alert传递一个参数
下面的函数判断是否按下修改键(shift、ctrl、alt)
window.onload=function() {
document.onclick=function(e){
alert(getKey(e));
}
}
function getKey(evt) {
var e = evt || window.event;
var keys = [];
if (e.shiftKey) keys.push('shift'); //给数组添加元素
if (e.ctrlKey) keys.push('ctrl');
if (e.altKey) keys.push('alt');
return keys;
}
注意:上面的功能实现的是在按住shift键、ctrl键、alt键的情况下,点击屏幕会输出按下的修改键
键盘事件
keydown 按下键盘
keyup 键盘起来的时候
keypress 按下字母键盘的时候
按下键盘并返回键码keycode (键码可以返回任意键的编码,而且字母不区分大小写)
document.onkeydown=function(e){
var event=e||window.event;
alert(event.keyCode)
}
但是使用了onkeypress来返回键码,在火狐浏览器中不支持(按下键盘的时候返回的是0),在谷歌浏览器和IE中虽然支持但是区分大小写
document.onkeypress=function(e){
var event=e||window.event;
alert(event.keyCode)
}
火狐和谷歌浏览器都支持的事件对象都支持charCode,和keyPress搭配来得到字符编码,注意IE的事件对象没有这个属性
document.onkeypress=function(e){
var event=e||window.event;
alert(event.charCode)
}
跨浏览器获得按下键盘的编码
window.onload=function() {
document.onkeypress=function(e){
alert(getCharCode(e))
}
}
function getCharCode(e){
var event=e||window.event;
if(typeof event.charCode=="number"){
return event.charCode;
}
else{
return event.keyCode;
}
}
w3c和IE的事件
得到事件的目标
,(鼠标点在哪里,就可以得到哪里的dom对象)
跨浏览器获得事件的目标
window.onload=function() {
document.onclick=function(e){
alert(getTarget(e).tagName);
}
}
function getTarget(e){
var event=e||window.event;
if(event.target){
return event.target;
}
else{
return event.srcElement
}
}
事件流
事件流有两种模式:冒泡和捕获
html代码
<div style="background: red;width: 100px;height: 100px" id="box">
<button > 点击</button>
</div>
js代码
window.onload=function() {
document.onclick=function(){
alert("documnet");
}
document.documentElement.onclick=function(){
alert("html");
}
document.body.onclick=function(){
alert("body");
}
document.getElementById("box").onclick=function(){
alert("box");
}
document.getElementsByTagName("button")[0].onclick=function(){
alert("input");
}
}
在任何的浏览器点击按钮的时候依次会输出 input box body html document
取消冒泡模式
document.getElementsByTagName("button")[0].onclick=function(e){
alert("input");
e.stopPropagation(); //IE不支持
}
只是取消了点击按钮的冒泡
跨浏览器阻止事件冒泡
function stopBubble(e){
var event=e||window.event;
(typeof event.stopPropagation=="function")? event.stopPropagation(): event.cancelBubble=true;
}
事件绑定
传统事件绑定
如果一个页面有两个或者多个js脚本文件,导致会有多个window.onload这两个事件,这就会导致第一个window.onload会被覆盖,解决的方法:在使用window.onload的时候,首先要检测是否存在window.onload是否是一个函数
下面就是解决覆盖的问题
window.onload=function () {
alert("dd");
}
if(typeof window.onload=="function"){
var saved=null;
saved=window.onload;
}window.onload=function () {
if(saved)saved();
alert("cc");
}
事件切换器
<style>
.red{
background: red;
width:200px;
height: 200px;
}
.blue{
background: blue;
width:200px;
height: 200px;
}
</style>
<body>
<div id="test" class="blue"></div>
</body>
js代码
window.onload=function () {
var test=document.getElementById("test");
console.log(test)
test.onclick=toBlue;
}
function toRed(){
this.className='red';
this.onclick=toBlue;
}
function toBlue(){
this.className='blue';
this.onclick=toRed;
}
注意,通过匿名函数执行一个函数,那么这个函数里面的this就会代表window,但是匿名函数这个this中还是属于当前对象的
test.onclick=function(){
alert(this); //div
toBlue();
};
function toBlue(){
alert(this); //会弹出window
this.className='blue';
this.onclick=toRed;
}
所以下面的这个代码也实现了事件的切换
test.onclick=function(){
toBlue.call(this);
};
function toRed(){
this.className='red';
this.onclick=toBlue;
}
function toBlue(){
this.className='blue';
this.onclick=toRed;
}
所以传统事件的绑定有许多的缺点,所以我们要自定义函数来实现事件的绑定
有一点值得注意window.onload相当于window[“onload”]
//obj 相当于window
//type 相当于onload
//fn 相当于function
function addEvent(obj,type,fn){
removeEvent(obj,type); //一道切的移除事件的函数
var saved=null;
if(typeof obj['on'+type]=='function'){
saved=obj['on'+type];
}
obj['on'+type]=function(){
if(saved){
saved();
}
//用它来做事件切换器 注意this
fn.call(this);
}
}
function removeEvent(obj,type){
if(typeof obj['on'+type]=='function') {
obj['on'+type]=null;
}
}
使用新的绑定事件的方式实现事件切换器
addEvent(window,'load',function () {
var test=document.getElementById("test");
addEvent(test,'click',toBlue)
})
function toRed(){
this.className='red';
addEvent(this,'click',toBlue);
}
function toBlue(){
this.className='blue';
addEvent(this,'click',toRed);
}
W3C事件绑定机制
DOM2级定义了两个事件的处理方法 添加事件 删除事件
也就是addEventListener()和removeEventListener()但是这两个方法只能在支持W3C的事件模型的浏览器上运行
传递的参数 对象.addEventListener('事件',事件处理函数,捕获(true)还是冒泡false)
window.addEventListener('load',function () {
alert(11);
},false)
window.addEventListener('load',function () {
alert(22);
},false)
1、DM2级事件模型的绑定事件解决了覆盖的问题(一次会弹出11 22)
window.addEventListener('load',init,false)
window.addEventListener('load',init,false)
window.addEventListener('load',init,false)
function init() {
alert(1);
}
2、相同的函数多次绑定到同一个函数的时候,会自动的屏蔽(会之弹出一次1,自动屏蔽)
window.addEventListener('load',function () {
var test=document.getElementById("test");
test.addEventListener('click',toBlue,false);
},false)
function toRed() {
this.className="red";
this.removeEventListener('click',toRed,false); //必须要有这一步,否则没有办法进行事件的切换
this.addEventListener('click',toBlue,false);
}
function toBlue() {
this.className="blue";
this.removeEventListener('click',toBlue,false); //必须要有这一步,否则没有办法进行事件的切换
this.addEventListener('click',toRed,false);
}
3、可以传递this,实现事件的切换器,直接在toRed使用this
test.addEventListener('click',function () {
alert(11);
},false);
test.addEventListener('click',toBlue,false);
4、添加一个额外的方法,会不会被覆盖或者只执行了一次,实现了点击的时候既可以弹出11也可以变色
综上所述,W3C的addEventListener和removeEventListener完美的解决了事件的绑定,但是IE8及其以下的版本都不支持DOM2级的这个事件模型,而是采用了自己的事件。
冒泡和捕获(设置true和false)
test.addEventListener('click',function () {
alert("div");
},true);
document.addEventListener('click',function () {
alert("document")
},true);
设置为了捕获,点击div的时候,先弹出document再弹出div
IE事件处理函数
注意以下的测试必须在IE8及以下完成:
attachEvent(‘on+事件名称’,’事件处理函数’)
detachEvent(‘事件名称’,’事件处理函数’)
因为IE8以下中的事件
1、不支持捕获,
2、IE事件不能屏蔽重复的函数
3、IE中的this指向的是widow而不是DOM对象(不可以传递this)
4、传统的IE事件模型上,IE是无法接收到event对象,但是使用了attachEvent()却可以
但是也解决了
1、覆盖问题
window.attachEvent('onload',function () {
alert(1);
})
window.attachEvent('onload',function () {
alert(2);
})
但是会先弹出2 在弹出1
让IE和W3C兼容这个事件切换器
1、跨浏览器添加事件
function addEvent(obj,type,fn) {
if(obj.addEventListener){
obj.addEventListener(type,fn,false);
}else if(obj.attachEvent){
obj.attachEvent('on'+type,fn)
}
}
2、夸浏览器移除事件
function removeEvent(obj,type,fn) {
if(obj.removeEventListener){
obj.removeEventListener(type,fn);
}else if(obj.detachEvent){
obj.detachEvent('on'+type,fn)
}
}
3、跨浏览器获取目标对象
function getTarget(e) {
if(e.target){
return e.target;
}
else if(window.event.srcElement){
return window.event.srcElement
}
}
事件对象的其他补充
W3C的relatedTarget这个属性可以在mouseover和mouseout事件中获取从哪里移入和从哪里移出
<span id="pox">
<div id="box"></div>
</span>
js代码
addEvent(window,'load',function () {
var box=document.getElementById("box");
addEvent(box,'mouseover',function (evt) {
alert(evt.relatedTarget) //得到移入box的最近的对象 会弹出span
})
})
跨浏览器阻止事件的默认行为
//跨浏览器阻止事件的默认行为
function predefault(evt) {
var event=evt||window.event;
if(event.preventDefault)
{
event.preventDefault();
}
else{
event.returnValue=false;
}
}