JavaScript 进阶营我的javaScript

js 事件模型 + ( 事件类型 )

2018-03-18  本文已影响265人  woow_wu7

Dom事件

事件是一种异步编程的实现方式,本质上是程序各个组成部分之间的通信。DOM支持大量的事件

(一) EventTarget接口

DOM的事件操作(监听和触发),都定义在EventTarget接口。Element节点、document节点和window对象,都部署了这个接口。

EventTarget接口有三个方法:

(1) addEventListener() 方法

addEventListener方法用于在当前节点或对象上,定义一个特定事件的监听函数。

target.addEventListener(type, listener, options);


window.onload = function() {
    var a = document.getElementById('a');
    var go = function() {
        console.log('这是addEventListener函数')
    }
    var to = function() {
        console.log('addEventListener可以为当前对象的同一事件,绑定不同的监听函数,先绑定的先执行')
    }
    a.addEventListener('click', go, false)   // 为a的 click事件 绑定了 监听函数go,在冒泡阶段触发
    a.addEventListener('click', to, false)   // 为当前对象 同一事件 绑定不同的 监听函数
}


--------------------------------------------------------------------------------


function hello() {
  console.log('Hello world');
}

document.addEventListener('click', hello, false);
document.addEventListener('click', hello, false);


// 执行上面代码,点击文档只会输出一行Hello world


function print(x) {
  console.log(x);
}

var el = document.getElementById('div1');
el.addEventListener('click', function () { print('Hello'); }, false);


---------------------------------------------


window.onload = function () {
    var a = document.getElementById('a');
    var go = function(x,e) {
        console.log(x)
        console.log(e,'每一个事件都会生成一个事件对象,作为参数,传给监听函数') //比如e.target等
    };
    a.addEventListener('click', function(e){ go('wang',e) }, false)
    var b = new Event('click');
    var c = a.dispatchEvent(b);

    console.log(c,'dispatchEvent()方法返回布尔值')
};

(2) removeEventListener() 方法

removeEventListener方法用来移除addEventListener方法添加的事件监听函数。

(3) dispatchEvent() 方法-------------触发事件

dispatchEvent方法在当前节点上触发指定事件,从而触发监听函数的执行。该方法返回一个布尔值,只要有一个监听函数调用了Event.preventDefault(),则返回值为false,否则为true。


para.addEventListener('click', hello, false);
var event = new Event('click');
para.dispatchEvent(event);

// 上面代码在当前节点触发了click事件。


----------------------------------------------------


 var c =  document.getElementById('c');
    function dispatch() {
      console.log(
        'dispatchEvent()作用是触发事件,参数是Event对象的实例,触发事件,从而出发事件绑定的监听函数'
       )
    }
    c.addEventListener('click', dispatch, false);
    var click = new Event('click');
    var d = c.dispatchEvent(click);   // dispatchEvent()事件执行后,返回一个布尔值
    console.log(d)      // true   


    // ------(只要有一个监听函数调用了 Event.preventDefault(),就会返回false,否则返回true)






(二) 监听函数

监听函数(listener)是事件发生时,程序所要执行的函数。

(1) HTML标签的on-属性

HTML语言允许在元素标签的属性中,直接定义某些事件的监听代码。


<body onload="doSomething()">
<div onclick="console.log('触发事件')">

// 上面代码为body节点的load事件、div节点的click事件,指定了监听函数。
// 使用这个方法指定的监听函数,只会在冒泡阶段触发。

<!-- 正确 -->
<body onload="doSomething()"> 



 // on-属性    方法,标签中  属性的值 是将要执行的代码,而不是函数(即 执行函数,而不是定义函数 )



<!-- 错误 -->
<body onload="doSomething">

el.setAttribute('onclick', 'doSomething()');

等同于

<body onclick="doSomething()">    // 这里的c,大小写都可以

(2) Element节点的事件属性

Element节点对象有事件属性,同样可以指定监听函数。

window.onload = doSomething;

div.onclick = function(event){
  console.log('触发事件');
};

// 使用这个方法指定的监听函数,只会在冒泡阶段触发。

(3) addEventListener方法

(4) 在监听函数中 this的指向

实际编程中,监听函数内部的this对象,常常需要指向触发事件的那个Element节点。


// HTML代码为
// <p id="para">Hello</p>

var id = 'doc';
var para = document.getElementById('para');

function hello(){
  console.log(this.id);  // addEventListener监听函数中的this,总是指向 触发事件的那个节点
}

para.addEventListener('click', hello, false);

总结


// JavaScript代码
element.onclick = print
element.addEventListener('click', print, false)
element.onclick = function () {console.log(this.id);}

// HTML代码
<element onclick="console.log(this.id)">


--------------------------------------------------------

// JavaScript代码
element.onclick = function (){ doSomething() };
element.setAttribute('onclick', 'doSomething()');

// HTML代码
<element onclick="doSomething()">





(三) 事件的传播

当一个事件发生以后,它会在不同的DOM节点之间传播(propagation)。这种传播分成三个阶段:

这种三阶段的传播模型,会使得一个事件在多个节点上触发。比如,假设点击<div>之中嵌套一个<p>节点。( phase是阶段的意思 )---------( bubbling是冒泡的意思 )

(四) 事件的代理

由于事件会在 冒泡阶段 向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。


var ul = document.querySelector('ul');

ul.addEventListener('click', function(event) {
  if (event.target.tagName.toLowerCase() === 'li') {
    // some code
  }
});


---------------------------------------
实例:


--
html部分:

    <div id="bubb" style="padding:20px;background:yellow; ">
        <p style="background:blueviolet">这是div中的p元素</p>
        <button style="background:royalblue">这是div中的按钮</button>
    </div>




--
js部分:

var e = document.getElementById('bubb');
    var func = function (event) {
        var tagname = event.target.tagName.toLowerCase();   // 目标节点的标签名
        if( tagname === 'p') {
            console.log('这是p元素')
        } else if( tagname === 'button') {
            console.log('这是button')
        } else {
            console.log('这是div父元素')
        }
    };
    e.addEventListener('click', func)

stopPropagation方法

p.addEventListener('click', function(event) {
  event.stopPropagation();    // stopPropagation() 阻止冒泡
});

// 用上面的代码以后,click事件在冒泡阶段到达<p>节点以后,就不再向上(父节点的方向)传播了。

stopImmediatePropagation方法

p.addEventListener('click', function(event) {
 event.stopImmediatePropagation();
});

p.addEventListener('click', function(event) {
 // 不会被触发
});





(5) Event对象

事件发生以后,会生成一个事件对象,作为参数传给监听函数。浏览器原生提供一个Event对象,所有的事件都是这个对象的实例,或者说继承了Event.prototype对象。

(1) Event构造函数接受两个参数:

event = new Event(typeArg, eventInit);

var ev = new Event(
  'look',
  {
    'bubbles': true,
    'cancelable': false
  }
);
document.dispatchEvent(ev);


// 上面代码新建一个look事件实例,然后使用dispatchEvent方法触发该事件。
例二:

para.addEventListener('click', hello, false);
var event = new Event('click');
para.dispatchEvent(event);   // 触发事件

例三:

window.onload = function () {
    var a = document.getElementById('a');
    var go = function(x,e) {
        console.log(x)
        console.log(e,'每一个事件都会生成一个事件对象,作为参数,传给监听函数,')
        console.log(e.bubbles,'e.bubbles')   // 在监听函数中,获取是否冒泡,只读
    };
    a.addEventListener('click', function(e){ go('wang',e) }, false)
    var b = new Event('click',{bubbles: true});  // 在创建click方法实例的时候,定义是否冒泡
    var c = a.dispatchEvent(b);

    console.log(c,'dispatchEvent()方法返回布尔值')
};

(2) event.bubbles

bubbles属性返回一个布尔值,表示当前事件是否会冒泡。该属性为只读属性,只能在新建事件时改变。除非显式声明,Event构造函数生成的事件,默认是不冒泡的。

(3) event.eventPhase

eventPhase属性返回一个整数值,表示事件目前所处的阶段。

(4) event.cancelable

cancelable属性返回一个布尔值,表示事件是否可以取消。该属性为只读属性,只能在新建事件时改变。除非显式声明,Event构造函数生成的事件,默认是不可以取消的。

(5) defaultPrevented

defaultPrevented属性返回一个布尔值,表示该事件是否调用过preventDefault方法。

(6) currentTarget

currentTarget属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点。
作为比较,target属性返回事件发生的节点。如果监听函数在捕获阶段和冒泡阶段触发,那么这两个属性返回的值是不一样的。

(7) target

target属性返回触发事件的那个节点,即事件最初发生的节点。如果监听函数不在该节点触发,那么它与currentTarget属性返回的值是不一样的。

(8) event.type

type属性返回一个字符串,表示事件类型,大小写敏感。

(9) event.detail

detail属性返回一个数值,表示事件的某种信息。具体含义与事件类型有关,对于鼠标事件,表示鼠标按键在某个位置按下的次数,比如对于dblclick事件,detail属性的值总是2。

(10) event.timeStamp

timeStamp属性返回一个毫秒时间戳,表示事件发生的时间。

(11) isTrusted

isTrusted属性返回一个布尔值,表示该事件是否为真实用户触发。

(12) event.preventDefault()

preventDefault方法取消浏览器对当前事件的默认行为

(13) event.stopPropagation()

stopPropagation方法阻止事件在 DOM 中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上新定义的事件监听函数。









事件类型

(一) 鼠标事件

(1) click事件

当用户在Element节点、document节点、window对象上单击鼠标(或者按下回车键)时,click事件触发。

(2) dblclick事件

dblclick事件当用户在element、document、window对象上,双击鼠标时触发。该事件会在mousedown、mouseup、click之后触发。

(3) mousedown事件

mousedown在按下鼠标键时触发。

(4) mouseup 事件

mouseup在释放按下的鼠标键时触发。

(5) mousemove事件

mousemove事件当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次代码。

(6) mouseover事件 和 mouseenter事件

mouseover事件和mouseenter事件,都是鼠标进入一个节点时触发。

(7) mouseout 事件,mouseleave 事件

mouseout事件和mouseleave事件,都是鼠标离开一个节点时触发。

(8) contextmenu 事件

contextmenu事件在一个节点上点击鼠标右键时触发,或者按下“上下文菜单”键时触发。




(二) 滚轮事件

(1) wheel事件

wheel事件是与鼠标滚轮相关的事件,目前只有一个wheel事件。用户滚动鼠标的滚轮,就触发这个事件。

var syntheticEvent = new WheelEvent("syntheticWheel", {"deltaX": 4, "deltaMode": 0});



(三) 键盘事件

(1)键盘事件用来描述键盘行为,主要有keydown、keypress、keyup三个事件。

(2) 如果用户一直按键不松开,就会连续触发键盘事件,触发的顺序如下。

keydown
keypress
keydown
keypress
(重复以上过程)
keyup

(3) 键盘事件使用 KeyboardEvent 对象表示,该对象继承了UIEvent和MouseEvent对象。浏览器提供KeyboardEvent构造函数,用来新建键盘事件的实例。

(4) altKey,ctrlKey,metaKey,shiftKey


   var inpu = document.getElementById('input');
    var keyDown = function (e) {
        console.log(e.ctrlKey, '是否按下了ctrl键')
        console.log(e.altKey, '是否按下了alt键')
        console.log(e.metaKey, '是否按下了win键')
        console.log(e.shiftKey, '是否按下了shift键')
        console.log(e.key,'e.key返回一个字符串,表示按下的键名')

        // 这里要注意:keypress 事件中ctrlKey,altKey,shiftKey,metaKey事件是undefined
        // 在keydown 和 keyup事件中是true和false
    }
    inpu.addEventListener('keydown', keyDown, false);  // keydown事件,触发keyDoen监听函数

(5) key 属性

key属性返回一个字符串,表示按下的键名。

var inpu = document.getElementById('input');
    var keyDown = function (e) {
        console.log(e.key,'e.key返回一个字符串,表示按下的键名')
    }  // keypress事件的监听函数中,传入的参数keyboardEvent,没有ctrl,alt,meta,shift属性

inpu.addEventListener('keydown', keyDown, false);  // keydown事件,触发keyDoen监听函数




(四) 进度事件

进度事件用来描述一个事件进展的过程,比如XMLHttpRequest对象发出的HTTP请求的过程、<img>、<audio>、<video>、<style>、<link>加载外部资源的过程。下载和上传都会发生进度事件。
abort事件:当进度事件被中止时触发。如果发生错误,导致进程中止,不会触发该事件。

image.addEventListener('load', function(event) {
  image.classList.add('finished');
});

image.addEventListener('error', function(event) {
  image.style.display = 'none';
});


上面代码在图片元素加载完成后,为图片元素的class属性添加一个值“finished”。

如果加载失败,就把图片元素的样式设置为不显示。


<img src="/wrong/url" onerror="this.style.display='none';" />

这样写能保证,发生加载错误时,onerror事件百分百会执行

(1) 进度事件使用ProgressEvent对象表示

ProgressEvent实例有以下属性。




(五) 拖拉事件

拖拉指的是,用户在某个对象上按下鼠标键不放,拖动它到另一个位置,然后释放鼠标键,将该对象放在那里。

拖拉的对象有好几种,包括Element节点、图片、链接、选中的文字等等。在HTML网页中,除了Element节点默认不可以拖拉,其他(图片、链接、选中的文字)都是可以直接拖拉的。为了让Element节点可拖拉,可以将该节点的draggable属性设为true。

(六) 触摸事件

触摸API由三个对象组成。

(七) 表单事件

(1)input事件 ----------- 输入时触发

input事件当<input>、<textarea>的值发生变化时触发。此外,打开contenteditable属性的元素,只要值发生变化,也会触发input事件。

input事件的一个特点,就是会连续触发,比如用户每次按下一次按键,就会触发一次input事件。

(2) select事件 ----------- 选中里面值时 触发

select事件当在<input>、<textarea>中选中文本时触发。

(3) Change事件 -------- 值改变且失去焦点时 触发,分下面三种情况

Change事件当<input>、<select>、<textarea>的值发生变化时触发。

(4) reset事件,submit事件

以下事件发生在表单对象上,而不是发生在表单的成员上。

(八) 文档事件

(1) hashchange事件,popstate事件

以下事件与文档的URL变化相关。

(1) hashchange事件

hashchange事件在URL的hash部分(即#号后面的部分,包括#号)发生变化时触发。如果老式浏览器不支持该属性,可以通过定期检查location.hash属性,模拟该事件

(2) popstate事件

popstate事件在浏览器的history对象的当前记录发生显式切换时触发。注意,调用history.pushState()或history.replaceState(),并不会触发popstate事件。该事件只在用户在history记录之间显式切换时触发,比如鼠标点击“后退/前进”按钮,或者在脚本中调用history.back()、history.forward()、history.go()时触发。

上一篇 下一篇

猜你喜欢

热点阅读