# EventTarget
# 构造
EventTarget
- 作用:构造一个事件监听器
- 调用:new EventTarget()
- 增加监听:target.addEventListener()
- 触发事件:target.dispatchEvent(new Event())
# addEventListener
- 作用:为文档上的元素绑定事件监听,触发函数
- 调用:element.addEventlistener(event, callback[, option | useCapture])
- 入参:String, Function[, Object | boolean]
- 返回:undefined
- tip:文档上的元素指Element/Window/Document/XMLHttpRequest/其他支持事件的对象
- DOM上onclick类的事件绑定都是以属性的形式存在DOM对象上,因此不能重复绑定
- addEventListener可以同时绑定多个事件,因为注册的是一个事件列表
# removeEventListener
- 作用:移除监听事件
- 调用:eventTarget.removeEventTarget(type, callback, options)
- 入参:String, Function[, Boolean | Object]
- 返回:undefined
<body>
<button id='btn'>按钮</button>
<script>
const btn = document.querySelector('#btn');
const callback1 = () => console.log('1');
const callback2 = () => console.log('2');
btn.addEventListener('click', callback1);
btn.addEventListener('click', callback2);
btn.click(); // 1 2
setTimeout(() => {
console.log('移除事件1,再点击');
btn.removeEventListener('click', callback1);
btn.click(); // 2
}, 2000)
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# dispatchEvent
- 作用:向指定目标派发事件
- 调用:element.dispatchEvent(event)
- 入参:Event
- 返回:undefined
只发射一次
- 每个事件只能被发射一次,多次发射报错
# Event属性
# Event
构造
- 作用:构造新的Event事件
- 调用:new Event(type[, {bubbles, cancelable, composed}])
- 入参:String[, {Boolean, Boolean, Boolean}]
# target
- 值:事件发起节点对象
- 获取:e.target
# currentTarget
- 作用:拿到事件当前传播到的node对象
- 获取:e.currentTarget
<body>
<div>
<button>按钮</button>
</div>
<script>
const button = document.querySelector('button');
const div = document.querySelector('div');
div.addEventListener('click', e => {
console.log(e.target); // <button>按钮</button>
console.log(e.currentTarget); // <div>...</div>
})
button.click();
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# type
- 值:事件的类型
- 返回:String
<body>
<button>按钮</button>
<script>
const button = document.querySelector('button');
button.addEventListener('go', function(e) {
console.log(e.type); // go
});
const e = new Event('go');
button.dispatchEvent(e);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# bubbles
- 作用:检测事件是否会冒泡
- 获取:event.bubbles
- 值:Boolean
<body>
<div>
<button>按钮1</button>
</div>
<script>
const div = document.querySelector('div');
const btn = document.querySelector('button');
btn.addEventListener('click', e => console.log(e.bubbles));
// div盒子在冒泡阶段等click事件触发
div.addEventListener('click', () => console.log('div说我被触发了'), false);
// new Event默认不冒泡
btn.dispatchEvent(new Event('click')); // false
console.log('等两秒');
// true div说我被触发了
setTimeout(() => btn.dispatchEvent(new Event('click', {bubbles: true})), 2000)
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# cancelable
- 作用:设置事件默认事件是否可被preventDefault()取消
- 获取:event.cancelable
- 值:Boolean
- tip:正常传播,只是禁止了默认事件
# defaultPrevented
- 作用:查看该事件是否调用了preventDefault方法
- 调用:e.defaultPrevented
- 返回:Boolean
- dispatchEvent发射的事件好像不生效?
- 手动触发可以
- 点击按钮,显示true
<body>
<button>按钮</button>
<script>
const button = document.querySelector('button');
button.addEventListener('click', function(e) {
e.preventDefault();
console.log(e.defaultPrevented); // true
})
// 生成的事件无效?
// const e = new Event('click');
// e.preventDefault();
// button.dispatchEvent(e);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# eventPhase
- 作用:查看当前事件传播到哪个阶段了
- 调用:event.eventPhase
- 返回:Number
值 | 含义 |
---|---|
0 | 事件没开始传播 |
1 | 事件在捕获阶段 |
2 | 事件到达target |
3 | 事件在冒泡阶段 |
<body>
<div>
<button>按钮</button>
</div>
<script>
const button = document.querySelector('button');
const div = document.querySelector('div');
div.addEventListener('click', function(e) {
console.log('div捕获:' + e.eventPhase); // 1
}, true);
button.addEventListener('click', function(e) {
console.log('button捕获:' + e.eventPhase); // 2
}, true);
button.addEventListener('click', function(e) {
console.log('button冒泡:' + e.eventPhase); // 2
});
div.addEventListener('click', function(e) {
console.log('div冒泡:' + e.eventPhase); // 3
});
const e = new Event('click');
console.log(e.eventPhase); // 0
button.dispatchEvent(e);
setTimeout(() => console.log('结束' + e.eventPhase)); // 0
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# isTrusted
- 作用:查看该事件是不是系统信任的浏览器发起事件【用户生成的返回false】
- 调用:event.isTrusted
- 返回:Boolean
- tip:只读属性
- dispatchEvent发起的值是false,点击时浏览器发起的值是true
<body>
<button>按钮</button>
<script>
const button = document.querySelector('button');
button.addEventListener('click', function(e) {
console.log(e.isTrusted); // false
});
const e = new Event('click');
button.dispatchEvent(e);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# Event方法
# preventDefault
- 作用:阻止浏览器默认事件作用触发
- 调用:e.preventDefault()
- tip:不影响自定义事件,不影响事件传播
# composedPath
- 作用:事件的传播路径
- 调用:e.composedPath()
- 返回:Array【栈结构】
返回值
- 0是target,最下面是window
- 从一开始就把路径存完了,并不是边执行边存的
<body>
<article>
<div>
<button>按钮</button>
</div>
</article>
<script>
const button = document.querySelector('button');
const div = document.querySelector('div');
button.addEventListener('click', function(e) {
console.log(e.composedPath()); // Array(7) [button, div ...]
});
div.addEventListener('click', function(e) {
console.log(e.composedPath()); // Array(7) [button, div ...]
},true);
const e = new Event('click');
button.dispatchEvent(e);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# stopImmediatePropagation
stop stopImmediatePropagation
- 翻译:停止立即传播
- 作用:不再调用其他的事件回调,并且阻止传播
- 调用:e.stopImmediatePropagation()
- 返回:undefined
- addEventListener同一个事件时是按序执行,stopImmediatePropagation之前的都执行,之后的都不执行
- 并且停止事件的传播
<body>
<article>
<div>
<button>按钮</button>
</div>
</article>
<script>
const button = document.querySelector('button');
const div = document.querySelector('div');
button.addEventListener('click', function(e) {
console.log('e的点击事件1');
});
button.addEventListener('click', function(e) {
console.log('e的点击事件2');
e.stopImmediatePropagation();
});
// 已被阻止剩下的事件回调执行,无
button.addEventListener('click', function(e) {
console.log('e的点击事件3');
});
// 已被停止事件传播,无
div.addEventListener('click', function(e) {
console.log('到div了');
});
const e = new Event('click');
button.dispatchEvent(e);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# stopPropagation
- 作用:停止事件传播,但本对象上的监听回调会执行完
- 调用:e.stopPropagation()
<body>
<article>
<div>
<button>按钮</button>
</div>
</article>
<script>
const button = document.querySelector('button');
const div = document.querySelector('div');
button.addEventListener('click', function(e) {
console.log('e的点击事件1');
});
button.addEventListener('click', function(e) {
console.log('e的点击事件2');
e.stopPropagation();
});
// 会执行完本对象的事件回调
button.addEventListener('click', function(e) {
console.log('e的点击事件3');
});
// 已被停止事件传播,无
div.addEventListener('click', function(e) {
console.log('到div了');
});
const e = new Event('click');
button.dispatchEvent(e);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 移动端事件
# clientX/pageX/screenX
e.targetTouches[0].clientX
是相对于浏览器左边缘距离e.targetTouches[0].screenX
是相对于屏幕左边缘距离e.targetTouches[0].pageX
是相对于页面左边缘距离,有可能发生了滚动
# touch事件和mouse事件打平
- 鼠标
mousemove
和touch
事件取x和y方法不一样 - mouse有移出屏幕的风险,会导致监听触发不符合预期
- mouse事件有x,y,touch事件只有clientX,clientY
- touch事件必须拿
targetTouches
或touches
获取clientX/clientY - mac的触控板是touch事件
// 打平移动端位置事件
const moveListener = (el, callback) => {
let mouseDown = false;
const touchMove = e => callback(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
const mouseDownEvent = () => mouseDown = true;
const mouseUp = () => mouseDown = false;
const mouseOut = () => mouseDown = false;
const mouseMove = (e) => {
if (!mouseDown) return;
callback(e.clientX, e.clientY);
}
el.addEventListener("touchmove", touchMove);
el.addEventListener("mousedown", mouseDownEvent);
el.addEventListener("mouseup", mouseUp);
el.addEventListener("mouseout", mouseOut);
document.addEventListener("mouseout", mouseOut);
el.addEventListener("mousemove", mouseMove);
return () => {
el.removeEventListener("touchmove", touchMove);
el.removeEventListener("mousedown", mouseDownEvent);
el.removeEventListener("mouseup", mouseUp);
el.removeEventListener("mouseout", mouseOut);
document.removeEventListener("mouseout", mouseOut);
el.removeEventListener("mousemove", mouseMove);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28