Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 33ebd91

Browse filesBrowse files
committed
2019.01.27 开始写重温基础 - 高级篇
1 parent b0cb8dc commit 33ebd91
Copy full SHA for 33ebd91

3 files changed

+320-13Lines changed: 320 additions & 13 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎Cute-JavaScript/Cute-JS/README.md‎

Copy file name to clipboardExpand all lines: Cute-JavaScript/Cute-JS/README.md
+5-4Lines changed: 5 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@
2727
15. [JS对象介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/1.JS对象介绍.md)
2828
16. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/2.JSON对象介绍.md)
2929
17. [WebAPI介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/3.WebAPI介绍.md)
30-
17. [相等性判断](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/4.相等性判断.md)
31-
32-
更新中
30+
18. [相等性判断](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/4.相等性判断.md)
31+
19. [闭包](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/5.闭包.md)
3332

3433
## JavaScript高级
35-
待补充
34+
19. [闭包](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level3/1.事件.md)
35+
36+
更新中
3637

3738
## 其他细节知识
3839
1. [JS中的高阶函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/other/1-JS中的高阶函数.md)
Collapse file

‎Cute-JavaScript/Cute-JS/level3/1.事件.md‎

Copy file name to clipboardExpand all lines: Cute-JavaScript/Cute-JS/level3/1.事件.md
+309-5Lines changed: 309 additions & 5 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
本文是 **重温基础** 系列文章的第二十篇。
2+
3+
这是第三个基础系列的第一篇,欢迎持续关注呀!
4+
**重温基础** 系列的【初级】和【中级】的文章,已经统一整理到我的【[Cute-JavaScript](http://js.pingan8787.com)】的JavaScript基础系列中。
25
今日感受:电影有时候看的是缘分。
36

4-
**本章节复习的是JS中的事件,事件冒泡捕获代理等等**
7+
**本章节复习的是JS中的事件,事件冒泡捕获代理模拟等等**
58

69
**前置知识:**
710
JavaScript与HTML的交互式通过**事件**来实现的,是文档或浏览器窗口中发生的一些特定的交互瞬间。
@@ -230,7 +233,7 @@ var my_event = {
230233
当触发一个DOM上的事件时,都会产生一个事件对象`event`,并作为参数传入事件处理程序,这个对象包含所有与事件相关的信息。包括导致事件的元素、事件类型等其他信息。
231234

232235
### 3.1 DOM中的事件对象
233-
无论指定事件处理程序时使用am方法(DOM0级方法或DOM2级方法),都会传入`event`对象:
236+
无论指定事件处理程序时使用什么方法(DOM0级方法或DOM2级方法),都会传入`event`对象:
234237
```js
235238
var leo = document.getElementById('leo');
236239
leo.onclick = function(event){
@@ -245,18 +248,319 @@ leo.addEventListener('click',function(event){
245248

246249
![event成员2](http://images.pingan8787.com/20190127%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1%E6%88%90%E5%91%982.png)
247250

251+
我们可以使用`event`中的对象和方法:
252+
* 阻止事件的默认行为
253+
```js
254+
var leo = document.getElementById('leo');
255+
leo.onclick = function(event){
256+
// 只有当 event 中的 cancelable 属性为true的事件
257+
event.preventDefault();
258+
}
259+
```
260+
* 立即停止事件在DOM的传播
261+
262+
通过调用`event.stopPropagation()`方法避免弹框出现两次。
263+
```js
264+
var leo = document.getElementById('leo');
265+
leo.onclick = function(event){
266+
alert('leo');
267+
event.stopPropagation();
268+
}
269+
document.body.onclick = function(event){
270+
alert('hello leo');
271+
}
272+
```
273+
274+
### 3.2 IE中的事件对象
275+
访问IE中的事件对象`event`,方法有多种,取决于事件处理程序的方法:
276+
* DOM0级方法,使用`window.event`
277+
278+
```js
279+
var leo = document.getElementById('leo');
280+
leo.onclick = function(){
281+
var event = window.event;
282+
alert(event.type); // 'click'
283+
}
284+
```
285+
286+
* IE的`attachEvent`方法,`event`作为参数传入(也可以使用`window.event`
287+
288+
```js
289+
var leo = document.getElementById('leo');
290+
leo.attachEvent('onclick',function(event){
291+
alert(event.type); // 'click'
292+
},false);
293+
```
294+
295+
### 3.3 跨浏览器的事件对象
296+
虽然DOM和IE中`event`对象不同,但我们也可以和前面的 **跨浏览器事件处理程序** 处理一样,通过他们之间的区别,实现映射:
297+
```js
298+
var my_event = {
299+
myAddFun : function(element, type, handler){
300+
// do some thing
301+
},
302+
// 返回对event的引用
303+
getMyEvent : function(event){
304+
return event?event:window.event;
305+
},
306+
// 返回事件的目标
307+
getMyTarget : function(event){
308+
return event.target || event.srcElement;
309+
},
310+
// 取消事件的默认行为
311+
preventDefault : function(event){
312+
if(event.preventDefault){
313+
event.preventDefault();
314+
}else {
315+
event.returnValue = false;
316+
}
317+
},
318+
319+
myRemoveFun : function(element, type, handler){
320+
// do some thing
321+
},
322+
323+
// 阻止事件流
324+
stopPropagetion : function(event){
325+
if(event.stopPropagetion){
326+
event.stopPropagetion();
327+
}else {
328+
event.cancelBubble = true;
329+
}
330+
}
331+
}
332+
333+
var leo = document.getElementById('leo');
334+
leo.onclick = function(event){
335+
alert('leo');
336+
event = my_event(event);
337+
my_event.stopPropagation(event);
338+
}
339+
340+
leo.onclick = function(event){
341+
alert('hello world');
342+
}
343+
```
248344

249345
## 4.事件类型
346+
Web浏览器中的事件类型有很多,**DOM3级事件**规定有以下几类事件类型:
347+
* **UI事件**:当用户与页面上元素交互时触发;
348+
* **焦点事件**:当元素失去或获取焦点时触发;
349+
* **鼠标事件**:当用户通过鼠标在页面操作时触发;
350+
* **滚轮事件**:当使用鼠标滚轮(或类似设备)时触发;
351+
* **文本事件**:当在文档中输入文本时触发;
352+
* **键盘事件**:当用户通过键盘操作时触发;
353+
* **合成事件**:当为IME输入字符时触发;
354+
* **变动事件**:当底层DOM结构变动时触发;
355+
356+
具体每个方法的详细介绍,可以查看**[W3school HTML DOM Event 对象](http://www.w3school.com.cn/jsref/dom_obj_event.asp)**
357+
或者查看《JavaScript高级程序设计(第三版)》的第362页开始。
358+
我后面会单独整理一篇,介绍这些事件的文章。
359+
250360

251361
## 5.事件委托
362+
简单理解就是讲一个响应事件委托到另一个元素。
363+
**事件委托**利用事件冒泡,指定一个事件处理程序来管理某一类型的所有事件,比如我们通过一个函数来代替其他三个函数:
364+
```html
365+
<ul id="btn">
366+
<li id="btn1">按钮1</li>
367+
<li id="btn2">按钮2</li>
368+
<li id="btn3">按钮3</li>
369+
</ul>
370+
```
371+
```js
372+
var btn1 = document.getElementById('btn1');
373+
var btn2 = document.getElementById('btn2');
374+
var btn3 = document.getElementById('btn3');
375+
// my_event 在前面定义了
376+
my_event.myAddFun(btn1, 'click', function(event){
377+
alert('btn1点击');
378+
});
379+
my_event.myAddFun(btn2, 'click', function(event){
380+
alert('btn2点击');
381+
});
382+
my_event.myAddFun(btn3, 'click', function(event){
383+
alert('btn3点击');
384+
});
385+
```
386+
下面我们在**DOM树层级更高的元素上添加一个事件处理函数**,来做事件委托,我们这么重写这段代码:
387+
```js
388+
var btn = document.getElementById('btn');
389+
my_event.myAddFun(btn, 'click', function(event){
390+
event = my_event.getMyEvent(event);
391+
var target = my_event.getMyTarget(event);
392+
switch(target.id){
393+
case "btn1":
394+
alert('btn1点击');
395+
break;
396+
case "btn2":
397+
alert('btn2点击');
398+
break;
399+
case "btn3":
400+
alert('btn3点击');
401+
break;
402+
}
403+
});
404+
```
405+
最适合采用事件委托技术的事件包括:`click`/`mousedown`/`mouseup`/`keyup`/`keydown`/`keypress`,虽然`mouseover``mouseout`事件也有冒泡,但因为不好处理它们并且经常需要重新计算元素位置。
406+
407+
可以看出,**事件委托**有以下优点:
408+
* 减少内存消耗
409+
* 动态绑定事件
252410

253411
## 6.事件模拟
412+
JavaScript的事件模拟主要用来在任意时刻触发特定事件。
413+
414+
### 6.1 DOM中的事件模拟
415+
`document`对象上使用`createEvent()`方法创建一个`event`对象。
416+
`createEvent()`接收一个参数,即要创建的事件类型的字符串。
417+
DOM2级中,所有这些字符串都使用英文复数形式,DOM3级中都变成单数,也可以是下面中的字符串:
418+
* UIEvents : 一般化的UI事件(鼠标和键盘事件都继承自UI事件)(DOM3级中`UIEvent`
419+
* MouseEvents : 一般化的鼠标事件(DOM3级中`MouseEvent`
420+
* MutationEvents : 一般化的DOM滚动事件(DOM3级中`MutationEvent`
421+
* HTMLEvents : 一般化的HTML事件(DOM3级中`HTMLEvent`
422+
423+
创建`event`之后,我们需要使用`dispatchEvent()`方法去触发这个事件,需要传入一个参数,参数是需要触发事件的event对象。
424+
425+
所有支持事件的DOM节点都支持这个方法。事件触发之后,事件就能照样冒泡并引发响应事件处理程序的执行。
426+
427+
#### 6.1.1 模拟鼠标事件
428+
使用`createEvent()`方法传入`MouseEvents`创建一个鼠标事件,返回的对象有一个`initMouseEvent()`方法,用于指定与该鼠标事件相关的信息,有15个参数:
429+
* type : 字符串,表示触发的事件类型,如`click`
430+
* bubble : 布尔值,表示是否冒泡,为了精确模拟鼠标事件,通常设置为true
431+
* cancelable :布尔值,表示是否可以取消,为了精确模拟鼠标事件,通常设置为true
432+
* view : 与事件关联的视图,基本都设置为`document.defaultView`
433+
* detail : 整数,与事件有关的详细信息,基本设置为0
434+
* screenX : 整数,事件相对屏幕的X坐标
435+
* screenY : 整数,事件相对屏幕的Y坐标
436+
* clientX : 整数,事件相对视口的X坐标
437+
* clientY : 整数,事件相对视口的Y坐标
438+
* ctrlKey : 布尔值,表示是否按下Ctrl键,默认false
439+
* altKey : 布尔值,表示是否按下Alt键,默认false
440+
* shiftKey : 布尔值,表示是否按下Shift键,默认false
441+
* metaKey : 布尔值,表示是否按下Meta键,默认false
442+
* button : 整数,表示按下哪个鼠标键,默认0
443+
* relatedTarget : 对象,表示与事件相关的对象,只在`mouseover``mouseout`时使用
444+
445+
案例:
446+
```js
447+
var btn = document.getElementById('btn');
448+
var myEvent = document.createEvent('MouseEvents');
449+
myEvent.initMouseEvent(
450+
'click', true, true, document.defaultView,
451+
0, 0, 0, 0, 0,
452+
false, false, false, false, 0, null
453+
)
454+
btn.dispatchEvent(myEvent);
455+
```
456+
457+
#### 6.1.2 模拟键盘事件
458+
DOM3级规定,使用`createEvent()`方法传入`KeyboardEvent`创建一个键盘事件,返回的对象有一个`initKeyEvent()`方法,有8个参数:
459+
* type : 字符串,表示触发的事件类型,如`keydown`
460+
* bubble : 布尔值,表示是否冒泡,为了精确模拟键盘事件,通常设置为true
461+
* cancelable :布尔值,表示是否可以取消,为了精确模拟键盘事件,通常设置为true
462+
* view : 与事件关联的视图,基本都设置为`document.defaultView`
463+
* key : 整数,表示按下的键的键码
464+
* localtion : 整数,表示按下哪里的键,默认0表示主键盘,1表示左,2表示右,3表示数字键盘,4表示移动设备(即虚拟键盘),5表示手柄
465+
* modifiers : 字符串,空格分隔的修改件列表,如"shift"
466+
* repeat : 整数,在一行中按了多少次这个键
467+
由于DOM3级不提倡使用`keypress`事件,因此只能用这个方式来模拟`keyup`/`keydown`事件。
468+
469+
模拟按住Shift和A键的案例:
470+
```js
471+
var btn = document.getElementById('btn');
472+
var myEvent;
473+
474+
// 以DOM3级方式创建
475+
if(document.implementation.hasFeature('KeyboardEvents', '3.0')){
476+
myEvent = document.createEvent('KeyboardEvent');
477+
myEvent.initKeyboardEvent(
478+
'keydown', true, true, document.defaultView,
479+
'a', 0, 'Shift', 0
480+
);
481+
}
482+
btn.dispatchEvent(myEvent);
483+
```
484+
485+
#### 6.1.3 模拟其他事件
486+
如模拟**变动事件****HTML事件**
254487

488+
* 模拟**变动事件**
255489

256-
## 参考文章:
257-
1. [MDN 闭包](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures#%E8%AF%8D%E6%B3%95%E4%BD%9C%E7%94%A8%E5%9F%9F)
258-
2. 《JavaScript高级程序设计》第13章 事件
490+
通过`createEvent()`传入`MutationEvents`参数创建,返回一个`initMutationEvent()`方法,这个方法接收参数包括:`type`/`bubbles`/`cancelable`/`relatedNode`/`preValue`/`newValue`/`attrName`/`attrChange`,下面模拟一个案例:
491+
```js
492+
var btn = document.getElementById('btn');
493+
var myEvent = document.createEvent('MutationEvents');
494+
myEvent.initMutationEvent(
495+
'DOMNodeInserted', true, false, someNode, '', '', '', 0
496+
);
497+
btn.dispatchEvent(myEvent);
498+
```
499+
500+
* 模拟**HTML事件**
501+
502+
通过`createEvent()`传入`HTMLEvents`参数创建,返回一个`initEvent()`方法,下面模拟一个案例:
503+
```js
504+
var btn = document.getElementById('btn');
505+
var myEvent = document.createEvent('HTMLEvents');
506+
myEvent.initEvent('focus', true, false);
507+
btn.dispatchEvent(myEvent);
508+
```
509+
510+
#### 6.1.4 自定义DOM事件
511+
通过`createEvent()`传入`CustomEvent`参数创建,返回一个`initCustomEvent()`方法,有4个参数:
512+
* type : 字符串,表示触发的事件类型,如`keydown`
513+
* bubble : 布尔值,表示是否冒泡,为了精确模拟键盘事件,通常设置为true
514+
* cancelable :布尔值,表示是否可以取消,为了精确模拟键盘事件,通常设置为true
515+
* detail : 对象,任意值,保存在`event`对象的`detail`属性中
516+
517+
案例:
518+
```js
519+
var btn = document.getElementById('btn');
520+
var myEvent;
521+
522+
// my_event在前面定义 2.6 跨浏览器事件处理程序
523+
my_event.addMyEvent(btn, 'myevent', function(event){
524+
alert('btn detail ', event.detail);
525+
});
526+
527+
my_event.addMyEvent(document, 'myevent', function(event){
528+
alert('document detail ', event.detail);
529+
});
530+
531+
532+
// 以DOM3级方式穿件
533+
if(document.implementation.hasFeature('CustomEvents', '3.0')){
534+
myEvent = document.createEvent('CustomEvent');
535+
myEvent.initCustomEvent(
536+
'myevent', true, false, 'hello leo',
537+
);
538+
btn.dispatchEvent(myEvent);
539+
}
540+
```
541+
542+
### 6.2 IE中的事件模拟
543+
IE8及之前的版本模拟事件和DOM中模拟思路相似:想创建`event对象`再指定信息,最后触发。
544+
区别在于,IE中使用`document.createEventObject()`方法创建`event对象`,并且不接收参数,返回一个通用`event对象`,我们要做的就是给这个`event对象`添加信息,最后在目标上调用`fireEvent()`方法,并接受两个参数(事件处理程序的名称和`event对象`)。
545+
在调用`fireEvent()`方法会自动添加`srcElement``type`属性,我们需要手动添加其他属性,下面模拟一个click事件:
546+
```js
547+
var btn = document.getElementById('btn');
548+
var myEvent = document.createEventObject();
549+
550+
myEvent.screenX = 100;
551+
myEvent.screenY = 0;
552+
myEvent.clientX = 100;
553+
myEvent.clientY = 0;
554+
myEvent.ctrlKey = false;
555+
myEvent.altKey = false;
556+
myEvent.shiftKey = false;
557+
myEvent.button = 0;
558+
559+
btn.fireEvent('onclick', event);
560+
```
259561

562+
## 参考文章
563+
1. 《JavaScript高级程序设计》第13章 事件
260564

261565
**本部分内容到这结束**
262566

Collapse file

‎Cute-JavaScript/README.md‎

Copy file name to clipboardExpand all lines: Cute-JavaScript/README.md
+6-4Lines changed: 6 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@
2626
## JavaScript中级
2727
15. [JS对象介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/1.JS对象介绍.md)
2828
16. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/2.JSON对象介绍.md)
29-
17. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/3.WebAPI介绍.md)
30-
31-
更新中
29+
17. [WebAPI介绍](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/3.WebAPI介绍.md)
30+
18. [相等性判断](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/4.相等性判断.md)
31+
19. [闭包](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level2/5.闭包.md)
3232

3333
## JavaScript高级
34-
待补充
34+
19. [闭包](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript/Cute-JS/level3/1.事件.md)
35+
36+
更新中
3537

3638
## 其他细节知识
3739
1. [JS中的高阶函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/other/1-JS中的高阶函数.md)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.