Maison  >  Article  >  interface Web  >  Une introduction détaillée au code graphique des événements JavaScript DOM

Une introduction détaillée au code graphique des événements JavaScript DOM

黄舟
黄舟original
2017-03-04 15:40:011189parcourir

Les événements sont des moments interactifs spécifiques qui se produisent dans un document ou une fenêtre de navigateur, tels qu'un clic, un double-clic, un survol de la souris, etc.

Flux d'événements

Le flux d'événements décrit l'ordre dans lequel les événements sont reçus de la page, ou l'ordre dans lequel les événements sont propagés dans la page.

  • Le flux d'événements d'IE est appelé event bubbling (event bubbling)  : l'événement démarre à partir de l'élément le plus spécifique, puis se propage jusqu'à l'étape de la fenêtre par objet étape.

  • Le flux d'événements proposé par l'équipe Netscape est appelé event capture (event capture)  : les événements commencent à être exécutés à partir de l'objet fenêtre le plus à l'extérieur, puis se propagent progressivement vers le bas jusqu'à l'élément le plus spécifique.

Faisons une petite expérience pour illustrer la différence entre ces deux flux d'événements :

// html 文档
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>事件流 实验</title>
</head>
<body>
  <p id="test" style="font-size:3em;">点我点我,我是p</p>
</body>
</html>
// 事件冒泡
var p = document.getElementById("test");
p.addEventListener("click",function(){
  console.log("i am p");
}, false);
document.body.addEventListener("click",function(){
  console.log("i am body");
}, false);
document.documentElement.addEventListener("click",function(){
  console.log("i am html");
}, false);
document.addEventListener("click",function(){
  console.log("i am document");
}, false);
window.addEventListener("click",function(){
  console.log("i am window");
}, false);

Une introduction détaillée au code graphique des événements JavaScript DOM

点击p,控制端会打印如下:
i am p
i am body
i am html
i am document
i am window
// 事件捕获
var p = document.getElementById("test");
p.addEventListener("click",function(){
  console.log("i am p");
}, true);
document.body.addEventListener("click",function(){
  console.log("i am body");
}, true);
document.documentElement.addEventListener("click",function(){
  console.log("i am html");
}, true);
document.addEventListener("click",function(){
  console.log("i am document");
}, true);
window.addEventListener("click",function(){
  console.log("i am window");
}, true);

Une introduction détaillée au code graphique des événements JavaScript DOM

La photo a été traitée deux fois et est légèrement moche, pardonnez-moi !

点击p,控制端会打印如下:
i am window
i am document
i am html
i am body
i am p

On peut voir que le bouillonnement d'événements et la capture d'événements sont deux flux d'événements complètement opposés.

Habituellement, le bouillonnement d'événements est généralement utilisé et la capture d'événements n'est utilisée que dans des circonstances particulières.

Le flux d'événements spécifié par les événements de niveau DOM2 comprend trois étapes : l'étape de capture d'événement, l'étape cible et l'étape de bouillonnement d'événement.

// 事件冒泡和事件捕获混合一下
var p = document.getElementById("test");
p.addEventListener("click",function(){
  console.log("i am p");
}, true);
document.body.addEventListener("click",function(){
  console.log("i am body");
}, false);    // 改为在冒泡阶段调用事件处理程序
document.documentElement.addEventListener("click",function(){
  console.log("i am html");
}, true);
document.addEventListener("click",function(){
  console.log("i am document");
}, true);
window.addEventListener("click",function(){
  console.log("i am window");
}, false);    // 改为在冒泡阶段调用事件处理程序

Cette image est tirée directement du livre. Créez simplement votre propre cerveau et ajoutez vous-même l'objet fenêtre !

Une introduction détaillée au code graphique des événements JavaScript DOM

点击p,控制端会打印如下:
i am document
i am html
i am p
i am body
i am window

Gestionnaire d'événements

Gestionnaire d'événements : fait référence à une fonction qui répond à un événement

Gestionnaires d'événements HTML

Chaque événement pris en charge par un élément peut être spécifié à l'aide d'un attribut HTML portant le même nom que le gestionnaire d'événements correspondant.

// 情况一
<button onclick="alert(&#39;I am button!&#39;);">按钮</button>
// 情况二
<button onclick="show();">按钮</button>
<script>
function show(){
  alert("I am button!");
}
</script>

Il est recommandé de ne jamais utiliser cette méthode pour ajouter des événements aux éléments, car cette méthode présente un énorme inconvénient, à savoir qu'elle rend le code HTML et JavaScript étroitement couplés, ce qui n'est pas conforme aux séparation du comportement et de la structure de la conception Web.

Gestionnaire d'événements de niveau DOM0

Chaque élément (y compris la fenêtre et le document) a son propre attribut de gestionnaire d'événements, tel que onclick, onmouseup etc.

Réécrivez le code ci-dessus comme suit :

<button id="test">按钮</button>
var button = document.getElementById("test");
button.onclick = function(){
  // this 对象指向 button 元素
  console.log(this);
  alert("I am button!");
};
/*  删除指定的事件处理程序  */
button.onclick = null;

Gestionnaire d'événement de niveau DOM2

L'événement de niveau DOM2 est défini Deux Les méthodes sont utilisées pour gérer l'opération de spécification et de suppression des gestionnaires d'événements : addEventListener() et removeEventListener().

Les deux méthodes ont trois paramètres. Le premier paramètre est le nom de l'événement, le deuxième paramètre est la fonction de gestionnaire d'événement et le troisième paramètre est une valeur booléenne. La valeur par défaut est false, ce qui signifie l'événement. Le gestionnaire est appelé pendant la phase de bouillonnement. Si cette valeur est vraie, cela signifie que le gestionnaire d'événements est appelé pendant la phase de capture.

Continuez à réécrire le code ci-dessus :

var button = document.getElementById("test");
function show(){
  // this 对象指向 button 元素
  console.log(this);
  alert("I am button!");
}
// 添加事件处理程序
button.addEventListener("click",show, false);
button.addEventListener("click",function(){
  alert("I am second alert!");
},false);
// 删除事件处理程序
button.removeEventListener("click",show, false); // 删除成功
button.removeEventListener("click",function(){   // 删除失败
  alert("I am second alert!");
},false);

Le principal avantage de l'utilisation de la méthode de niveau DOM2 pour ajouter des gestionnaires d'événements est que vous pouvez ajouter plusieurs gestionnaires d'événements pour un élément.

Si le gestionnaire d'événements ajouté par addEventListener() est une fonction anonyme, ce gestionnaire d'événements ne peut pas être supprimé par removeEventListener().

Gestionnaire d'événements IE

IE8 et les versions antérieures d'IE ne prennent en charge que le bouillonnement d'événements et ne prennent pas en charge addEventListener() et removeEventListener(), mais il en implémente deux des méthodes similaires à ces deux méthodes : attachEvent() et detachEvent(). Ces deux méthodes n'ont que deux paramètres, un nom d'événement (onclick, pas click) et une fonction de gestion d'événement.

Contrairement à addEventListener(), lors de l'utilisation de la méthode attachEvent(), la fonction de gestion des événements s'exécutera dans la portée globale, elle est donc égale à window, ce qui nécessite une attention particulière.

var button = document.getElementById("test");
button.attachEvent("onclick", function(){
  // this 对象指向了全局作用域,即 window
  console.log(this);
  alert("I am button!");
});
button.attachEvent("onclick",function(){
  alert("I am second alert!");
}); 
// 上面也是为同一个按钮绑定了两个事件处理程序
button.detachEvent("onclick",function(){ // 删除失败
  alert("I am second alert!");
});

N'utilisez pas ces deux fonctions sauf si vous souhaitez rendre votre programme compatible avec le navigateur IE8.

Comportement par défaut du navigateur

Pour certains événements spécifiques, le navigateur a son comportement par défaut. Par exemple : cliquer sur un lien passera à la page spécifiée, cliquer sur le bouton droit de la souris fera apparaître le menu contextuel du navigateur, et appuyer sur Entrée lors du remplissage d'un formulaire le soumettra automatiquement au serveur, etc.

Le comportement par défaut du navigateur et le comportement de bouillonnement sont indépendants. L'annulation du comportement par défaut d'un événement n'annulera pas le comportement de bouillonnement d'un événement, et vice versa. Plusieurs gestionnaires d'événements pour le même élément sont également indépendants les uns des autres.

<p>
  <a id="test" href="http://baidu.com">点我点我,我是链接</a>
</p>
var link = document.getElementById("test");
// 方法一   event.preventDefault()
link.onclick = function(event){
  console.log("You click!");
  event.preventDefault();
};
// 方法二   return false
link.onclick = function(event){
  console.log("You click!");
  return false;
};

Référence : Événement-4. Comportement par défaut du navigateur-Yu Qing

Événement d'objet d'événement

Lorsqu'un événement sur le DOM est déclenché, un événement d'objet événement sera généré. Cet objet contient toutes les informations liées à l'événement.

event 对象只存在于事件处理程序执行期间,一旦执行完毕,立即被销毁。

<p>
  <a id="test" href="http://baidu.com">点我点我,我是链接</a>
</p>
/* 下列 event 对象的属性和方法都是只读的  */
var link = document.getElementById("test");
link.onclick = function(event){
  // 判断当前事件是否会向 DOM 树上层元素冒泡
  console.log(event.bubbles);

  // 判断是否可以取消事件的默认行为
  console.log(event.cancelable);
  // 使用该方法可以取消事件的默认行为(使用前提是 cancelable 属性的值为 true)
  event.preventDefault();
  // 判断是否已经调用了 preventDefault() 方法(DOM3级事件新增)
  console.log(event.defaultPrevented);

  // 指向事件遍历 DOM 时,识别事件的当前目标对象
  console.log(event.currentTarget);
  // 指向触发事件的对象
  console.log(event.target);

  // 表示事件流当前处于哪一个阶段
  // 值为 1 表示在捕获阶段,值为 2 表示处于目标阶段,值为 3 表示在冒泡阶段
  console.log(event.eventPhase);

  // 返回一个字符串, 表示该事件对象的事件类型
  console.log(event.type);

  // 立即停止当前事件在 DOM 层次中的传播,即取消进一步的事件捕获或冒泡
  event.stopPropagation();
};

为了进一步说明 event.stopPropagation() 的运行效果,借用前面的代码,更改如下:

// 事件冒泡和事件捕获混合一下
var p = document.getElementById("test");
p.addEventListener("click",function(){
  console.log("i am p");
}, true);
document.body.addEventListener("click",function(){
  console.log("i am body");
}, false);    // 改为在冒泡阶段调用事件处理程序
document.documentElement.addEventListener("click",function(){
  console.log("i am html");
  event.stopPropagation();    // 立即停止事件在 DOM 中的传播
}, true);
document.addEventListener("click",function(){
  console.log("i am document");
}, true);
window.addEventListener("click",function(){
  console.log("i am window");
}, false);    // 改为在冒泡阶段调用事件处理程序
点击p,控制端会打印如下:
i am document
i am html

看到了吧,后面元素的事件就不会被激发了。

事件类型

UI 事件

UI 事件指的是简单的用户界面事件

load 事件:当页面所有资源(比如图像、css文件、js文件等资源)完全加载完毕后,就会触发 window 上面的 load 事件。

当然,我们也可以单独为某个元素设置 load 事件,比如为一个图片绑定这个事件,就可以检测这个图片是否加载完毕了。

<img  id="myImg" src="1.jpg" / alt="Une introduction détaillée au code graphique des événements JavaScript DOM" >
var img = document.getElementById("myImg");
img.onload = function(){
  alert("Image loaded!");
};

scroll 事件:在文档被滚动期间,重复触发该事件。

window.onscroll = function(){
  console.log("Scroll!");
};

焦点事件

焦点事件会在页面元素获得或失去焦点时触发。

注意:默认情况下,只有部分 html 元素能获得鼠标焦点(如 input,a),很大一部分 html 元素是不能获得鼠标焦点的(如 p,img),这些能够获得鼠标焦点的元素就是 focusable 元素。

不过,可以通过为这些默认没有焦点事件的元素添加一个 tabindex 属性,从而使它可以支持焦点事件。

  • document.activeElement:返回当前页面中获得焦点的元素,如果没有某个元素获得焦点,则该属性的值为当前页面中的元素

  • document.hasFocus():判断当前文档或者当前文档的子节点是否获得了焦点

  • HTMLElement.focus():使得指定的元素获得焦点(前提是这个元素是一个可以获得焦点的元素)

  • HTMLElement.blur():移除当前元素获得的焦点

上面是一些 HTML5 中添加的焦点管理 API。下面说焦点事件:

  • focus 事件:在元素获得焦点时触发,这个事件不会冒泡

  • blur 事件:在元素失去焦点时触发,这个事件不会冒泡

  • focusin 事件:在元素获得焦点时触发,与 focus 事件等价,但会冒泡

  • focusout 事件:在元素失去焦点时触发,与 blur 事件等价,但会冒泡

<img  id="img" src="1.jpg" tabindex="1" / alt="Une introduction détaillée au code graphique des événements JavaScript DOM" >
var img = document.getElementById("img");
document.body.onscroll = function() {
    img.blur();
};
img.onfocus = function() {
    console.log("Img focused!");
};
img.onblur = function() {
    console.log("Img lose focus!");
};
img.onclick = function() {
    console.log(document.activeElement);
    console.log(document.hasFocus());
};

注意: focusin 和 focusout 事件,所有的 Firefox 版本都不支持,看这里。chrome 和 safari 中只有通过 addEventListener 方式绑定这两个事件才能正常使用,其他方式绑定都不行。

说说focus /focusin /focusout /blur 事件(推荐)
(WHATWG)Focus management APIs

鼠标与滚轮事件

DOM3 级事件中定义了9个鼠标事件。

<body>
 <p id="test">
   <button>按钮</button>
 </p>
</body>
// css
p {
    width: 300px;
    height: 300px;
    margin: 50px auto;
    border: 1px solid #aaa;
  }

mouseover 事件:鼠标指针首次进入一个元素边界之内时触发,会冒泡

mouseout 事件:鼠标指针移出这个元素边界时触发,会冒泡

var test = document.getElementById("test");
test.onmouseover = function(event){
  event.target.style.border = "3px solid #666";
};
test.onmouseout = function(event){
  event.target.style.border = "none";
};

mouseenter 事件:鼠标指针首次移动到元素范围之内时触发,不冒泡

mouseleave 事件:鼠标指针移动到元素范围之外时触发,不冒泡

var test = document.getElementById("test");
test.onmouseenter = function(event){
  event.target.style.border = "10px solid #666";
};
test.onmouseleave = function(event){
  event.target.style.border = "none";
};

mousemove 事件:当鼠标在元素内部移动时重复触发,会冒泡

// 这里写一个鼠标在 body 内移动时,背景颜色随机变化的脚本
document.body.onmousemove = function(){
  var r = Math.floor(Math.random() * 256)
      g = Math.floor(Math.random() * 256)
      b = Math.floor(Math.random() * 256);
  document.body.style.background = "rgb("+r+","+g+","+b+")";
};

mousedown 事件:用户通过按下任意鼠标按钮时触发

mouseup 事件:用户释放鼠标按钮时触发

click 事件:用户单击鼠标左键时或按下回车键时触发

dblclick 事件:用户双击鼠标左键时触发

var body = document.body;
body.onmousedown = function(){
  console.log("Mouse down!");
};
body.onmouseup = function(){
  console.log("Mouse up!");
};
body.onclick = function(){
  console.log("One click!");
};
body.ondblclick = function(){
  console.log("Double click!");
};
// 双击 body,控制端打印:
Mouse down!
Mouse up!
One click!
Mouse down!
Mouse up!
One click!
Double click!

只有在同一个元素上相继触发 mousedown 和 mouseup 事件,才会触发 click 事件,缺一不可。类似地,只有连续触发两次 click 事件,才会触发 dblclick 事件。

获取点击坐标

  • clientX 和 clientY:鼠标指针在视口中的坐标

  • pageX 和 pageY:鼠标指针在页面中的坐标

  • screenX 和 screenY:鼠标指针在屏幕中的坐标

在页面没有滚动的情况下,pageX 和 pageY 的值与 clientX 和 clientY 的值相等。

document.body.onclick = function() {
  console.log("Client: " + "(" + event.clientX + "," + event.clientY + ")");
  console.log("Page: " + "(" + event.pageX + "," + event.pageY + ")");
  console.log("Screen: " + "(" + event.screenX + "," + event.screenY + ")");
};

键盘与文本事件

  • keydown 事件:当用户按下任意键时触发,而且如果按住不放的话,会重复触发此事件

  • keypress 事件:当用户按下任意字符键时触发,而且如果按住不放的话,会重复触发此事件

  • keyup 事件:当用户释放键盘上的按键时触发

在用户按下一个字符键并且立马释放这个按键的过程中,先触发 keydown 事件,再触发 keypress 事件,最后触发 keyup 事件。

window.onkeydown = function() {
  console.log("on key down");
};
window.onkeyup = function() {
  if (event.keyCode === 65) {
    console.log(event.key);
  }
  console.log("one key up");
};
window.onkeypress = function() {
  console.log("one key press");
};

为了知道自己按下的是哪个按键,可以使用 event.which 来获得你按下按键的键码(比如字母 A 的键码为 65)。也可以通过键码属性(event.keyCode)来对特定的按键来进行响应。键码参考表

发生 keypress 事件时,会存在一个 charCode 属性,返回这个按键代表字符的 ASCII 编码。ASCII table

event.which 返回一个 keyCode 或 charCode 值,详情看下面代码

String.fromCharCode() 静态方法可以将 event.which 转化为相应的字符。

// 请自行粘贴复制于浏览器控制端测试
// 分别输入 a 和 A
// A和a 的 ASCII码分别为65,97
window.onkeydown = function(){
  if(event.keyCode === 65){
    console.log("(keydown keyCode)You press &#39;a&#39; or &#39;A&#39;!");
  }
  if(event.charCode === 65){
    console.log("(keydown charCode)You press &#39;A&#39;!");
  }
  console.log("keydown event.which = " + event.which);
  console.log("(keydown:)" + String.fromCharCode(event.which));
};
window.onkeypress = function(){
  if(event.keyCode === 65){
    console.log("(keypress keyCode)You press &#39;A&#39;!");
  }
  if(event.charCode === 65){
    console.log("(keypress charCode)You press &#39;A&#39;,not &#39;a&#39;!");
  }
  console.log("keypress event.which = " + event.which);
  console.log("(keypress:)" + String.fromCharCode(event.which));
};

在 DOM3 级事件中,做了一些变化,不再推荐使用 keyCode、charCode、which 属性,而是出现了两个新属性:key 和 char,用来替代 keyCode 和 charCode 属性。

但是不建议使用 key、char 属性,因为有一部分浏览器对他支持的不是很好。点这里

参考:JavaScript 事件——“事件类型”中“键盘与文本事件”的注意要点

变动事件

变动事件是在 DOM 结构发生变化时触发

在 DOM2 中定义了多个变动事件,但是在 DOM3 中又废除了一些,在这里先简单提一下有这个东西,以后用到再作补充。

HTML5 事件

contextmenu 事件:单击鼠标右键,会触发这个事件并调出页面的上下文菜单。这个事件是鼠标事件的一种,并且支持冒泡。

在上面的例子中,我们演示了利用 contextmenu 事件来设置自定义右键菜单,以及屏蔽右键菜单。

然而,屏蔽右键菜单却难不倒高手,Greasy Fork 上面有一个脚本(网页限制解除),专门来打破对右键菜单有限制的页面。

beforeunload 事件:当浏览器窗口,文档或其资源将要卸载时或者刷新页面时,会触发这个事件【MDN】

下面有几点需要注意一下:

1. 如果处理函数为 Event 对象的 returnValue 属性赋值非空字符串,浏览器会弹出一个对话框,来询问用户是否确定要离开当前页面。没有赋值时,该事件不做任何响应。

2. 从2011年5月25号开始,HTML5规范指出在此事件处理函数中,对于window.alert(), window.confirm(), 和 window.prompt() 的调用会被忽略。

3. 旧版本的浏览器可能会在提示框里显示返回的信息,但是新版本浏览器都默认采用浏览器内设的提示信息。

// 复制粘贴于浏览器控制端,然后关闭页面,会出现提示框
window.addEventListener("beforeunload", function() {
  var message = "你真的要离开吗?";
  event.returnValue = message;
  return message;
}, false);

DOMContentLoaded 事件:在页面文档形成完整的 DOM 树时触发,不理会图像、js文件、css文件等资源是否加载完毕

这个事件可以为 document 或 window 绑定,但实际目标是 document。这个事件会冒泡。

注意:这个事件与 load 事件是不一样的,正常情况下,会早于 load 事件被触发。

感觉篇幅太长了,事件委托移动设备中的事件事件对内存性能的影响等内容将在以后逐渐写出。

以上就是JavaScript DOM 事件初探的图文代码详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn