この記事では、JavaScript でのイベント モデルの詳細な説明 (コード例) を紹介します。必要な方は参考にしていただければ幸いです。 ###############イベント#########
ユーザーと Web ページ間の対話はイベントによって実現されます。イベントは当初、サーバーの負荷を分散する手段として使用されていました。独自の API 仕様。
イベントトリガーメカニズムに関して、両社は、ページのトリガーメカニズムは、特定の要素がクリックされたときに現在のターゲット要素のイベントをトリガーするだけではないと考えています。
例: ページに複数の同心円があります。最も内側の円をクリックすると、実際にはこの円の外側を含む円をクリックすることになります。両社はこの点で同意していますが、イベント ストリームの伝播シーケンスは、イベント バブリングとイベント キャプチャという 2 つの異なるソリューションを使用して実装されています。
1. イベント バブリング
IE ブラウザは、古いバージョンから常にイベント バブリング メカニズムをサポートしています。いわゆるイベント バブリングとは、イベント ストリームがより具体的な要素から開始され、継続することを意味します。非特定的な要素の拡散について。
はターゲット要素から親要素に伝播されます。
<div>
<div></div>
</div>
<script>
function childEventHandler(event) {
console.log(this);
console.log("child 被点击了");
}
function parentEventHandler(event) {
console.log(this);
console.log("parent 被点击了");
}
function bodyEventHandler(event) {
console.log(this);
console.log("body 被点击了");
}
function htmlEventHandler(event) {
console.log(this);
console.log("html 被点击了");
}
function documentEventHandler(event) {
console.log(this);
console.log("document 被点击了");
}
function windowEventHandler(event) {
console.log(this);
console.log("window 被点击了");
}
var bodyEl = document.getElementsByTagName("body")[0];
var htmlEl = document.getElementsByTagName("html")[0];
var win = window;
var parentEl = document.getElementById("parent");
var childEl = document.getElementById("child");
childEl.onclick = childEventHandler;
parentEl.onclick = parentEventHandler;
bodyEl.onclick = bodyEventHandler;
htmlEl.onclick = htmlEventHandler;
document.onclick = documentEventHandler;
win.onclick = windowEventHandler;
</script>
ログイン後にコピー
下図のように、子のidを持つ要素をクリックすると、子からウィンドウオブジェクトにイベントフローが伝播します。
![1542771922695402.png JavaScriptによるイベントモデルの詳細説明(コード例)](https://img.php.cn//upload/image/841/162/464/1542771922695402.png)
![1542771928259918.png JavaScriptによるイベントモデルの詳細説明(コード例)](https://img.php.cn//upload/image/763/847/889/1542771928259918.png)
最新のブラウザはすべてイベント バブリングをサポートしています。
2. イベント キャプチャ
Netscape によるイベント キャプチャは、イベント ストリームが不特定の要素からトリガーされ、その後特定の要素に広がります。つまり、親要素からターゲット要素に伝播されます。
![1542771943833963.png JavaScriptによるイベントモデルの詳細説明(コード例)](https://img.php.cn//upload/image/967/755/706/1542771943833963.png)
イベント キャプチャは IE 9 からサポートされ、古いバージョンのブラウザと互換性がないため、使用する人は少なくなります。
3. イベント フロー
DOM では、イベントにはイベント キャプチャ、ターゲット ステージ、イベント バブリングの 3 つのステージが含まれると規定しています。
IE 9 以降のブラウザでは、イベント フローの順序として、最初にイベント キャプチャが行われ、イベントがインターセプトされ、次にターゲット ステージに入り、実際のターゲットがイベントを受信し、最後にイベントがバブルアップすることが規定されています。このステージがイベントに応答していることを確認できます。
前の子要素を例に挙げると、子要素がイベントを受け取るまで (ウィンドウから親へ)、それがイベントのキャプチャ段階です。子要素に関しては、この時点でイベントが処理され、その後ウィンドウ オブジェクトにバブリングされます。バブリング段階でもイベントを処理できます。イベントを処理できるイベントバブリングの特徴を踏まえて、それに関連するイベント委任の仕組みについては後述します。
![1542771964940815.png JavaScriptによるイベントモデルの詳細説明(コード例)](https://img.php.cn//upload/image/694/497/375/1542771964940815.png)
4. イベント バインディング
HTML とイベント間のバインディングには 3 つの形式があります:
1.
<div></div>
2.
var childEl = document.getElementById("child");
childEl.onclick = function() {
console.log('hello');
}
3.
var childEl = document.getElementById("child");
childEl.addEventListener('click', function() {
console.log('hello');
}, false);
ログイン後にコピー
JavaScriptこれはシングルスレッド言語であり、要素でイベントがトリガーされると、イベントにバインドされた関数があるかどうかを確認し、存在しない場合は何も行いません。関数はイベントキューに配置され、実行後にメインスレッドイベントが実行されるのを待ちます。
上記のコードの最初のバインディングは HTML にイベントを書き込みますが、この方法でコードを記述することは推奨されません。
2 番目のタイプのバインディングは、イベントを要素オブジェクトにバインドします。この書き込み方法は主にイベントを上書きするのが簡単です。
3 番目のバインディング、まず 3 番目のパラメーターはブール値で、デフォルトは false です。これは、イベント ハンドラーがイベント バブリング ステージで呼び出されることを意味します。これが true の場合、それは、イベントハンドラはイベントキャプチャ関数で呼び出されます。
イベントを処理したいが、要素のイベント バインディングは処理したくない場合、メモリ リークが発生しやすい場合は、要素のイベント バインディングを空に設定する必要があります。
第一种写法:
childEl.onclick = null;
第三种写法:
function eventHandler() {
console.log('hello');
}
childEl.addEventListener('click', eventHandler, false);
childEl.removeEventListener('click', eventHandler, false);
ログイン後にコピー
5. イベントの委任 (イベント プロキシ)
イベントの委任は、より具体的な要素から開始され、不特定の要素に広がり続けます。
まず、リスト ul がある場合、リスト要素の li クリックごとにイベント ハンドラーがトリガーされます。要素に 1 つずつイベントをバインドすると、効率は明らかに悪くなります。
同時に、新しい要素が追加されると、イベントが正常にバインドされない場合があります。一緒に見てみましょう:
- menu-1
- menu-2
- menu-3
- menu-4
<script>
window.onload = function() {
var menu = document.getElementById("menu");
var item = menu.getElementsByClassName('menu-item');
for (var i = 0; i < item.length; i++) {
item[i].onclick = (function(i) {
return function() {
console.log(i);
}
}(i))
}
var addBtnEl = document.getElementById("addBtn");
addBtnEl.onclick = function() {
var newEl = document.createElement('li');
newEl.innerHTML = "menu-new"
menu.appendChild(newEl);
}
}
</script> 新しく追加されたメニュー new をクリックしても応答がなく、イベントがバインドされていないことを示していますが、イベントをバインドしたくないことがわかります。新しい要素が追加されるたびにこの新しい要素を追加するという非効率な作業の繰り返しは避けるべきです。
我们通过事件委托的思路来想,事件流的传播,目标元素本身依然会有事件,但同时,冒泡出去后,更高层次的 dom 也能处理事件程序。那么,我们只需要给高层次节点绑定事件,通过判断具体是触发的哪个子节点,再做相应的事件处理。
- menu-1
- menu-2
- menu-3
- menu-4
<script>
window.onload = function() {
var menu = document.getElementById("menu");
menu.onclick = function(event) {
var e = event || window.event;
var target = e.target || e.srcElement;
console.log(e);
switch (target.textContent) {
case "menu-1":
console.log("menu-1 被点击了");
break;
case "menu-2":
console.log("menu-2 被点击了");
break;
case "menu-3":
console.log("menu-3 被点击了");
break;
case "menu-4":
console.log("menu-4 被点击了");
break;
case "menu-new":
console.log("menu-new 被点击了");
break;
}
}
var addBtnEl = document.getElementById("addBtn");
addBtnEl.onclick = function() {
var newEl = document.createElement('li');
newEl.innerHTML = "menu-new"
menu.appendChild(newEl);
}
}
</script>
menu 列表的每个子菜单元素的事件都能正确响应,新增的 menu-new 同样也能正确响应事件。
事件委托的好处在于,我们不用给每个元素都一一地手动添加绑定事件,避免重复低效的工作。
其次,事件委托更少得获取 dom, 初始化元素对象和事件函数,能有效减少内存占用。
每当将事件程序指定给元素时,html 代码和 js 代码之间就建立了一个连接,这种连接越多,网页就执行起来越慢,所以事件委托能有效减少连接树,提高网页性能。
总结
用户与网页的交互是通过事件进行的,事件模型分为事件冒泡和事件捕获,事件冒泡的兼容性更好,应用更广,同时通过事件冒泡,可以建立事件委托,提升网页性能。
以上がJavaScriptによるイベントモデルの詳細説明(コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。