javascript打造跨浏览器事件处理机制[Blue-Dream出品]_javascript技巧
使用类库可以比较容易的解决兼容性问题.但这背后的机理又是如何呢? 下面我们就一点点铺开来讲.
首先,DOM Level2为事件处理定义了两个函数addEventListener和removeEventListener, 这两个函数都来自于EventTarget接口.
element.addEventListener(eventName, listener, useCapture);
element.removeEventListener(eventName, listener, useCapture);
EventTarget接口通常实现自Node或Window接口.也就是所谓的DOM元素.
那么比如window也就可以通过addEventListener来添加监听.
function loadHandler() {
console.log('the page is loaded!');
}
window.addEventListener('load', loadHandler, false);
移除监听通过removeEventListener同样很容易做到, 只要注意移除的句柄和添加的句柄引用自一个函数就可以了.
window.removeEventListener('load', loadHandler, false);
如果我们活在完美世界.那么估计事件函数就此结束了.
但情况并非如此.由于IE独树一帜.通过MSDHTML DOM定义了attachEvent和detachEvent两个函数取代了addEventListener和removeEventListener.
恰恰函数间又存在着很多的差异性,使整个事件机制变得异常复杂.
所以我们要做的事情其实就转移成了.处理IE浏览器和w3c标准之间对于事件处理的差异性.
在IE下添加监听和移除监听可以这样写
function loadHandler() {
alert('the page is loaded!');
}
window.attachEvent('onload', loadHandler); // 添加监听
window.detachEvent('onload', loadHandler); // 移除监听
从表象看来,我们可以看出IE与w3c的两处差异:
1. 事件前面多了个"on"前缀.
2. 去除了useCapture第三个参数.
其实真正的差异远远不止这些.等我们后面会继续分析.那么对于现在这两处差异我们很容易就可以抽象出一个公用的函数
function addListener(element, eventName, handler) {
if (element.addEventListener) {
element.addEventListener(eventName, handler, false);
}
else if (element.attachEvent) {
element.attachEvent('on' + eventName, handler);
}
else {
element['on' + eventName] = handler;
}
}
function removeListener(element, eventName, handler) {
if (element.addEventListener) {
element.removeEventListener(eventName, handler, false);
}
else if (element.detachEvent) {
element.detachEvent('on' + eventName, handler);
}
else {
element['on' + eventName] = null;
}
}
上面函数有两处需要注意一下就是:
1. 第一个分支最好先测定w3c标准. 因为IE也渐渐向标准靠近. 第二个分支监测IE.
2. 第三个分支是留给既不支持(add/remove)EventListener也不支持(attach/detach)Event的浏览器.
性能优化
对于上面的函数我们是运用"运行时"监测的.也就是每次绑定事件都需要进行分支监测.我们可以将其改为"运行前"就确定兼容函数.而不需要每次监测.
这样我们就需要用一个DOM元素提前进行探测. 这里我们选用了document.documentElement. 为什么不用document.body呢? 因为document.documentElement在document没有ready的时候就已经存在. 而document.body没ready前是不存在的.
这样函数就优化成
var addListener, removeListener,
/* test element */
docEl = document.documentElement;
// addListener
if (docEl.addEventListener) {
/* if `addEventListener` exists on test element, define function to use `addEventListener` */
addListener = function (element, eventName, handler) {
element.addEventListener(eventName, handler, false);
};
}
else if (docEl.attachEvent) {
/* if `attachEvent` exists on test element, define function to use `attachEvent` */
addListener = function (element, eventName, handler) {
element.attachEvent('on' + eventName, handler);
};
}
else {
/* if neither methods exists on test element, define function to fallback strategy */
addListener = function (element, eventName, handler) {
element['on' + eventName] = handler;
};
}
// removeListener
if (docEl.removeEventListener) {
removeListener = function (element, eventName, handler) {
element.removeEventListener(eventName, handler, false);
};
}
else if (docEl.detachEvent) {
removeListener = function (element, eventName, handler) {
element.detachEvent('on' + eventName, handler);
};
}
else {
removeListener = function (element, eventName, handler) {
element['on' + eventName] = null;
};
}
这样就避免了每次绑定都需要判断.
值得一提的是.上面的代码其实也是有两处硬伤. 除了代码量增多外, 还有一点就是使用了硬性编码推测.上面代码我们基本的意思就是断定.如果document.documentElement具备了add/remove方法.那么element就一定具备(虽然大多数情况如此).但这显然是不够安全.
不安全的检测
下面两个例子说明.在某些情况下这种检测不是足够安全的.
// In Internet Explorer
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
if (xhr.open) { } // Error
var element = document.createElement('p');
if (element.offsetParent) { } // Error
如: 在IE7下 typeof xhr.open === 'unknown'. 详细可参考feature-detection
所以我们提倡的检测方式是
var isHostMethod = function (object, methodName) {
var t = typeof object[methodName];
return ((t === 'function' || t === 'object') && !!object[methodName]) || t === 'unknown';
};
这样我们上面的优化函数.再次改进成这样
var addListener, docEl = document.documentElement;
if (isHostMethod(docEl, 'addEventListener')) {
/* ... */
}
else if (isHostMethod(docEl, 'attachEvent')) {
/* ... */
}
else {
/* ... */
}
丢失的this指针
this指针的处理.IE与w3c又出现了差异.在w3c下函数的指针是指向绑定该句柄的DOM元素. 而IE下却总是指向window.
// IE
document.body.attachEvent('onclick', function () {
alert(this === window); // true
alert(this === document.body); // false
});
// W3C
document.body.addEventListener('onclick', function () {
alert(this === window); // false
alert(this === document.body); // true
});
这个问题修正起来也不算麻烦
if (isHostMethod(docEl, 'addEventListener')) {
/* ... */
}
else if (isHostMethod(docEl, 'attachEvent')) {
addListener = function (element, eventName, handler) {
element.attachEvent('on' + eventName, function () {
handler.call(element, window.event);
});
};
}
else {
/* ... */
}
我们只需要用一个包装函数.然后在内部将handler用call重新修正指针.其实大伙应该也看出了,这里还偷偷的修正了一个问题就是.IE下event不是通过第一个函数传递,而是遗留在全局.所以我们经常会写event = event || window.event这样的代码. 这里也一并做了修正.
修正了这几个主要的问题.我们这个函数看起来似乎健壮了很多.我们可以暂停一下做下简单的测试, 测试三点
1. 各浏览器兼容 2. this指针指向兼容 3. event参数传递兼容.
测试代码如下:

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Une brève introduction à la programmation GUI python L'interface graphique (Graphical User Interface, interface utilisateur graphique) est un moyen qui permet aux utilisateurs d'interagir graphiquement avec les ordinateurs. La programmation GUI fait référence à l'utilisation de langages de programmation pour créer des interfaces utilisateur graphiques. Python est un langage de programmation populaire qui fournit une riche bibliothèque GUI, ce qui rend la programmation GUI Python très simple. Introduction à la bibliothèque GUI Python Il existe de nombreuses bibliothèques GUI en Python, dont les plus couramment utilisées sont : Tkinter : Tkinter est la bibliothèque GUI fournie avec la bibliothèque standard Python. Elle est simple et facile à utiliser, mais ses fonctions sont limitées. PyQt : PyQt est une bibliothèque graphique multiplateforme dotée de fonctions puissantes.

Introduction CircularQueue est une amélioration des files d'attente linéaires, qui a été introduite pour résoudre le problème du gaspillage de mémoire dans les files d'attente linéaires. Les files d'attente circulaires utilisent le principe FIFO pour y insérer et supprimer des éléments. Dans ce tutoriel, nous aborderons le fonctionnement d'une file d'attente circulaire et comment la gérer. Qu'est-ce qu'une file d'attente circulaire ? La file d'attente circulaire est un autre type de file d'attente dans la structure de données où le front-end et le back-end sont connectés l'un à l'autre. Il est également connu sous le nom de tampon circulaire. Il fonctionne de la même manière qu’une file d’attente linéaire, alors pourquoi devons-nous introduire une nouvelle file d’attente dans la structure des données ? Lors de l'utilisation d'une file d'attente linéaire, lorsque la file d'attente atteint sa limite maximale, il peut y avoir de l'espace mémoire avant le pointeur de queue. Cela entraîne une perte de mémoire et un bon algorithme devrait être capable d’utiliser pleinement les ressources. Afin de résoudre le gaspillage de mémoire

Bibliothèque de traitement d'événements en PHP8.0 : Événement Avec le développement continu d'Internet, PHP, en tant que langage de programmation back-end populaire, est largement utilisé dans le développement de diverses applications Web. Dans ce processus, le mécanisme événementiel est devenu un élément très important. La bibliothèque de traitement d'événements Event en PHP8.0 nous fournira une méthode de traitement d'événements plus efficace et plus flexible. Qu'est-ce que la gestion des événements ? La gestion des événements est un concept très important dans le développement d'applications Web. Les événements peuvent être n'importe quel type de ligne utilisateur

Les événements bouillonnants signifient que dans le développement Web, lorsqu'un événement est déclenché sur un élément, l'événement se propage aux éléments supérieurs jusqu'à ce qu'il atteigne l'élément racine du document. Cette méthode de propagation est comme une bulle qui monte progressivement du bas, c'est pourquoi on l'appelle un événement bouillonnant. Dans le développement réel, connaître et comprendre le fonctionnement des événements bouillonnants est très important pour gérer correctement les événements. Ce qui suit présentera en détail le concept et l’utilisation des événements bouillonnants à travers des exemples de code spécifiques. Tout d'abord, nous créons une simple page HTML avec un élément parent et trois enfants

Dans Vue, il y a souvent des composants imbriqués et les événements doivent être transmis entre ces composants imbriqués. Dans Vue, l'événement $emit est utilisé pour la communication d'événements entre les composants. Cependant, dans certains cas, nous devons transmettre le gestionnaire d'événements d'un composant parent à un composant enfant imbriqué. Dans ce cas, l'utilisation de l'événement $emit n'est pas appropriée. À ce stade, vous pouvez utiliser les $listeners fournis par Vue pour transmettre la fonction de traitement des événements. Alors, que sont les $auditeurs ?

Analyse de la directive v-on dans Vue : Comment gérer les événements de soumission de formulaire Dans Vue.js, la directive v-on est utilisée pour lier les écouteurs d'événements et peut capturer et traiter divers événements DOM. Parmi eux, le traitement des événements de soumission de formulaire est l'une des opérations courantes dans Vue. Cet article explique comment utiliser la directive v-on pour gérer les événements de soumission de formulaire et fournit des exemples de code spécifiques. Tout d'abord, il est nécessaire de préciser que l'événement de soumission de formulaire dans Vue fait référence à l'événement déclenché lorsque l'utilisateur clique sur le bouton de soumission ou appuie sur la touche Entrée. Dans Vue, vous pouvez passer

Scénarios d'application du bouillonnement d'événements et types d'événements qu'il prend en charge. Le bouillonnement d'événements signifie que lorsqu'un événement sur un élément est déclenché, l'événement sera transmis à l'élément parent de l'élément, puis à l'élément ancêtre de l'élément jusqu'à ce qu'il soit transmis. est transmis au nœud racine du document. Il s'agit d'un mécanisme important du modèle d'événement et propose un large éventail de scénarios d'application. Cet article présentera les scénarios d'application du bouillonnement d'événements et explorera les types d'événements qu'il prend en charge. 1. Scénarios d'application La diffusion d'événements propose un large éventail de scénarios d'application dans le développement Web. Voici plusieurs scénarios d'application courants. validation du formulaire dans le formulaire

Étude approfondie de l'implémentation du code clé de PHP et Vue dans la fonction de carte cérébrale Résumé : Cet article explorera en profondeur l'implémentation du code clé de PHP et Vue dans la fonction de carte cérébrale. La cartographie cérébrale est un outil graphique couramment utilisé pour afficher les structures et les relations de pensée. Il est largement utilisé dans des domaines tels que la planification de projets, la gestion des connaissances et l'organisation de l'information. En acquérant les connaissances pertinentes de PHP et Vue, nous pouvons implémenter une application de cartographie cérébrale simple mais puissante. Comprendre PHPPHP est un langage de script côté serveur couramment utilisé. Il est facile à apprendre et hautement évolutif
