Quand j'implémente cela en utilisant du CSS pur. J'ai commencé à utiliser JavaScript et des classes de style pour compléter les fonctionnalités.
Ensuite, j'ai quelques idées, je souhaite utiliser des événements délégués (délégation d'événements) mais je ne veux pas avoir de dépendances, brancher des bibliothèques, y compris jQuery. Je dois mettre en œuvre moi-même la délégation d’événements.
Voyons d’abord ce qu’est la délégation événementielle ? Comment fonctionnent-ils et comment mettre en œuvre ce mécanisme.
Regardons d’abord un exemple simple.
Supposons que nous ayons un ensemble de boutons. Je clique sur un bouton à la fois, puis je souhaite que l'état cliqué soit défini sur "actif". Annuler l'actif lorsque vous cliquez à nouveau.
Ensuite, nous pouvons écrire du HTML :
<ul class="toolbar"> <li><button class="btn">Pencil</button></li> <li><button class="btn">Pen</button></li> <li><button class="btn">Eraser</button></li> </ul>
Je peux utiliser certains événements Javascript standard pour gérer la logique ci-dessus :
var buttons = document.querySelectorAll(".toolbar .btn"); for(var i = 0; i < buttons.length; i++) { var button = buttons[i]; button.addEventListener("click", function() { if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }); }
Cela a l'air bien, mais Cela ne fonctionne pas réellement comme vous l'espériez.
Si vous avez une certaine expérience en développement JavaScript, ce problème sera évident.
Pour les non-initiés, la variable bouton est fermée, et le bouton correspondant sera retrouvé à chaque fois... mais en fait il n'y a qu'un seul bouton ici ; il sera réaffecté à chaque boucle.
La première boucle pointe vers le premier bouton, puis le deuxième. Mais lorsque vous cliquez, la variable bouton pointe toujours vers le dernier élément du bouton. C'est le problème.
Ce dont nous avons besoin, c'est d'une portée stable ;
var buttons = document.querySelectorAll(".toolbar button"); var createToolbarButtonHandler = function(button) { return function() { if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }; }; for(var i = 0; i < buttons.length; i++) { buttons[i].addEventListener("click", createToolBarButtonHandler(buttons[i])); }
Remarque* La structure du code ci-dessus est un peu compliquée. Vous pouvez également simplement utiliser une fermeture pour fermer et enregistrer la variable de bouton actuelle, comme indiqué ci-dessous :
var buttons = document.querySelectorAll(".toolbar .btn"); for(var i = 0; i < buttons.length; i++) { (function(button) { button.addEventListener("click", function() { if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }); })(buttons[i]) }
<ul class="toolbar"> <li><button id="button_0001">Foo</button></li> <li><button id="button_0002">Bar</button></li> // ... 997 more elements ... <li><button id="button_1000">baz</button></li> </ul>
var buttons = document.querySelectorAll(".toolbar button"); var toolbarButtonHandler = function(e) { var button = e.currentTarget; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); }; for(var i = 0; i < buttons.length; i++) { button.addEventListener("click", toolbarButtonHandler); }
Cependant, nous pouvons faire mieux.
Supposons que nous ajoutions dynamiquement quelques boutons à cette liste. Ensuite, nous ajouterons et supprimerons également des liaisons d'événements pour ces éléments dynamiques. Ensuite, nous devons conserver les variables utilisées par ces fonctions de traitement et le contexte actuel, ce qui semble peu fiable.
Il existe peut-être d'autres moyens.
Commençons par bien comprendre comment fonctionnent les événements et comment ils sont diffusés dans les DOM.
Comment fonctionnent les événements
Voici un exemple HTML :
Lorsque vous cliquez sur le bouton A, le chemin de l'événement ressemblera à ceci :<html> <body> <ul> <li id="li_1"><button id="button_1">Button A</button></li> <li id="li_2"><button id="button_2">Button B</button></li> <li id="li_3"><button id="button_3">Button C</button></li> </ul> </body> </html>
Notez que cela signifie que vous pouvez capturer l'événement généré par votre clic sur le chemin de l'événement. Nous sommes très sûrs que cet événement passera définitivement par leur élément parent ul. Nous pouvons lier notre traitement d'événements à l'élément parent et simplifier notre solution. C'est ce qu'on appelle la délégation d'événements et le proxy (événements délégués).START | #document \ | HTML | | BODY } CAPTURE PHASE | UL | | LI#li_1 / | BUTTON <-- TARGET PHASE | LI#li_1 \ | UL | | BODY } BUBBLING PHASE | HTML | v #document / ENDCopier après la connexion
Remarque* En fait, les mécanismes événementiels développés par Flash/Silverlight/WPF sont très similaires. Voici leur organigramme d'événements. Sauf que Silverlight 3 utilise l'ancienne version du modèle d'événement d'IE avec uniquement l'étape de bouillonnement, il comporte essentiellement ces trois étapes. (Le traitement des événements de l'ancienne version d'IE et SL3 n'a qu'un processus de bouillonnement de l'objet déclencheur vers l'objet racine, ce qui peut simplifier le mécanisme de traitement des événements.)
委托(代理)事件是那些被绑定到父级元素的事件,但是只有当满足一定匹配条件时才会被挪。
让我们看一个具体的例子,我们看看上文的那个工具栏的例子:
<ul class="toolbar"> <li><button class="btn">Pencil</button></li> <li><button class="btn">Pen</button></li> <li><button class="btn">Eraser</button></li> </ul>
因为我们知道单击button元素会冒泡到UL.toolbar元素,让我们将事件处理放到这里试试。我们需要稍微调整一下:
var toolbar = document.querySelector(".toolbar"); toolbar.addEventListener("click", function(e) { var button = e.target; if(!button.classList.contains("active")) button.classList.add("active"); else button.classList.remove("active"); });
这样我们清理了大量的代码,再也没有循环了。注意我们使用了e.target代替了之前的e.currentTarget。这是因为我们在一个不同的层次上面进行了事件侦听。
e.target 是当前触发事件的对象,即用户真正单击到的对象。
e.currentTarget 是当前处理事件的对象,即事件绑定的对象。
在我们的例子中e.currentTarget就是UL.toolbar。
注* 其实不止事件机制,在整个UI构架上FLEX(不是Flash) /Silverlight /WPF /Android的实现跟WEB也非常相似,都使用XML(HTML)实现模板及元素结构组织,Style(CSS)实现显示样式及UI,脚本(AS3,C#,Java,JS)实现控制。不过Web相对其他平台更加开放,不过历史遗留问题也更多。但是几乎所有的平台都支持Web标准,都内嵌有类似WebView这样的内嵌Web渲染机制,相对各大平台复杂的前端UI框架和学习曲线来说,使用Web技术实现Native APP的前端UI是非常低成本的一项选择。
以上就是理解JavaScript中的事件路由冒泡过程及委托代理机制的内容,更多相关内容请关注PHP中文网(www.php.cn)!