効率的なWebフロントエンドプログラムの作成方法は、フロントエンド開発を行うたびに無意識のうちに検討する問題です。数年前、Yahooの素晴らしいフロントエンドエンジニアは、Webフロントエンドのパフォーマンスを向上させることに関する本を発表しました。これは、Web開発技術業界全体で感覚を引き起こし、神秘的なWebフロントエンドの最適化の質問を路上でのキャベツにし、Webフロントエンドの最適化は、初心者と大きなジャイアントの両方が答える簡単な質問になりました。業界全体が衝撃的な秘密に対する答えを知っている場合、既存の最適化テクノロジーは、開発したウェブサイトの定性的な飛躍をもはや生成できなくなります。 Webサイトのパフォーマンスを作成するには、他の人のWebサイトよりも優れた開発を行うために、より深く考え、より良いスキルを予約する必要があります。
JavaScriptのイベントシステムは、私が考える最初のブレークスルーポイントです。なぜJavaScriptイベントシステムなのですか? Webフロントエンドには、HTML、CSS、JavaScriptの3つのテクノロジーが含まれていることは誰もが知っています。 HTMLとCSSがどのように組み合わされているかは明らかです:スタイル、クラス、ID、およびHTMLタグ。話すことは何もありませんが、JavaScriptがHTMLとCSSの中間にどのように入り、3つを統合しますか?最後に、このエントリポイントがJavaScriptのイベントシステムであることがわかりました。私たちが記述したJavaScriptコードの長さであっても、イベントシステムを介してHTMLとCSSに最終的に反映されます。したがって、イベントシステムは3つの統合のエントリポイントであるため、特に今日のますます複雑なWebページで、ページに多数のイベント操作が必然的に行われると考えていました。これらのイベントがなければ、私たちが注意深く書いたJavaScriptコードはライブラリでのみ使用でき、ヒーローは役に立たない。ページには多数のイベント機能があるため、イベント機能を作成するときに効率に影響を与える問題はありますか?私が研究した答えは、それが実際の効率性の問題であり、深刻な効率の問題でもあるということです。
私の答えを明確にするために、JavaScriptのイベントシステムを詳細に説明したいと思います。
イベントシステムは、JavaScript、HTML、およびCSSの融合のエントリポイントです。この点は、Javaの主な機能のようなものです。すべての魔法がここから始まります。では、ブラウザはこのエントリをどのように完了しますか?私は3つの方法を勉強しました、それらは次のとおりです。
方法1:HTMLイベント処理
HTMLイベント処理は、イベント関数をHTMLタグに直接書き込むことです。この書き込み方法はHTMLタグと密接に結びついているため、HTMLイベント処理と呼ばれます。たとえば、次のコード:
コードコピーは次のとおりです。
<入力型= "button" id = "btn" name = "btn" onclick = "alert( 'click me!')"/>
クリックイベント機能が複雑な場合、このようなコードを書くことは間違いなく不便を引き起こします。したがって、頻繁に関数を外部に記述し、onclickは関数名を直接呼び出します。たとえば
コードコピーは次のとおりです。
<入力型= "button" id = "btn" name = "btn" onclick = "btnclk()"/>
関数btnclk(){
アラート( "Click Me!");
}
上記の執筆方法は非常に美しい執筆方法であるため、多くの人々は最近無意識にそれを使用していますが、多くの人々は、後者の執筆方法が実際に以前の執筆方法ほど強くないことを知らないかもしれません。これは、フロントエンドの最適化の原則に従って、JavaScriptコードがページの下部にあることが多いため、ブロッキングのないロードロードスクリプトテクノロジーを少し前に研究する際に遭遇した問題でもあります。ページがスクリプトによってブロックされている場合、HTMLタグで参照される関数はまだ実行されていない可能性があります。この時点で、[ページ]ボタンをクリックすると、結果が「xxx関数が未定義のエラーです」と報告されます。 JavaScriptでは、このようなエラーはTry The Catchによってキャッチされます。したがって、コードをより堅牢にするために、次の書き直しができます。
コードコピーは次のとおりです。
<input type = "button" id = "btn" name = "btn" onclick = "try {btnclk();} catch(e){}"/>
上記のコードを見ることは、嫌な人が説明できるものではありません。
方法2:DOM0レベルイベント処理
DOM0レベルのイベント処理は、今日のすべてのブラウザがサポートするイベント処理です。互換性の問題はありません。そのような文章を見ると、Webのフロントエンドを興奮させるすべての人になります。 DOM0イベント処理のルールは次のとおりです。各DOM要素には独自のイベント処理属性があり、次のコードなどの関数を割り当てることができます。
コードコピーは次のとおりです。
var btndom = document.getElementById( "btn");
btndom.onclick = function(){
アラート( "Click Me!");
}
Dom0レベルのイベントで処理されるイベント属性は、「on+イベント名」の形式で定義され、属性全体は小文字にあります。 DOM要素はJavaScriptコードのJavaScriptオブジェクトであることがわかっているため、JavaScriptオブジェクトの観点からDOM0レベルのイベント処理を理解するのは非常に簡単です。たとえば、次のコード:
コードコピーは次のとおりです。
btndom.onclick = null;
次に、ボタンクリックイベントがキャンセルされます。
次のコードを見てみましょう。
コードコピーは次のとおりです。
btndom.onclick = function(){
アラート( "Click Me!");
}
btndom.onclick = function(){
アラート( "me1111をクリック!");
}
次の関数は、最初の関数を上書きします。
方法3:DOM2イベント処理とIEイベント処理
DOM2イベント処理は標準化されたイベント処理ソリューションですが、IEブラウザーは一連の関数を開発しており、関数はDOM2イベント処理に似ていますが、コードはそれとは異なります。
方法3を説明する前に、いくつかの概念を追加する必要があります。そうしないと、方法3の意味合いを説明できません。
最初の概念は、イベントフローです
ページ開発では、この状況に遭遇することがよくあります。ページの作業間隔は、JavaScriptのドキュメントで表すことができます。ページにDivがあります。 DIVは、ドキュメント要素のオーバーレイと同等です。 divにはボタン要素があります。ボタン要素はdivのオーバーレイであり、これはドキュメントのオーバーレイと同等です。そのため、このボタンをクリックすると、このクリック動作が実際にボタンで発生するだけではありません。 Divとドキュメントの両方がクリック操作に使用されます。 Logicによれば、これらの3つの要素はクリックイベントをトリガーできます。イベントストリームは、上記のシナリオの概念を説明しています。イベントストリームは、ページから受信したイベントの順序を意味します。
2番目の概念:イベントバブルとイベントキャプチャ
イベントバブルは、イベントフローの問題を解決するためにMicrosoftによって提案されたソリューションであり、イベントキャプチャはNetscapeが提案するイベントフローソリューションです。彼らの原則は次のとおりです。
バブルイベントは、Divから始まり、ボディと最終的にドキュメントが続き、イベントキャプチャが逆転し、最初にドキュメントが逆になり、次にボディが続き、最後にターゲットエレメントDivが続きます。対照的に、Microsoftのソリューションはより人道的であり、人々の営業習慣に沿って、Netscapeのソリューションは非常に厄介です。これがブラウザ戦争の結果です。 Netscapeは遅くなり、ユーザーが慣れているコードを犠牲にすることにより、イベントフローの問題を解決します。
Microsoftは、業界でのIEイベント処理として一般的に知られているバブルイベントと組み合わせて、新しいイベントシステムを設計しました。 IEイベント処理の方法は、次のコードに示されています。
コードコピーは次のとおりです。
var btndom = document.getElementById( "btn");
btndom.attachevent( "onclick"、function(){
アラート( "Click Me!");
});
IEの下のDOM要素のAttachmentEventメソッドを介してイベントを追加します。 DOM0イベント処理と比較して、イベントを追加する方法は属性からメソッドに変更されているため、イベントを追加すると、パラメーターをメソッドに渡す必要があります。 AttachmentEventメソッドは2つのパラメーターを受信します。最初のパラメーターはイベントタイプです。イベントタイプの命名は、DOM0イベント処理でイベントの命名と同じです。 2番目のパラメーターはイベント関数です。この方法を使用する利点は、以下に示すように、同じ要素にクリックイベントを追加する場合です。
コードコピーは次のとおりです。
btndom.attachevent( "onclick"、function(){
アラート( "Click Me!");
});
btndom.attachevent( "onclick"、function(){
アラート(「私もクリックしてください!」);
});
実行すると、両方のダイアログボックスが正常にポップアップされ、DOM要素に複数の異なるクリックイベントを追加できます。イベントが欲しくない場合はどうなりますか?私たちは何をすべきですか?イベントを削除するためのDetacheventメソッドを提供します。パラメーターリストはAttachEventと同じです。特定のクリックイベントを削除する場合は、次のコードに示すように、追加イベントと同じパラメーターを渡すだけです。
コードコピーは次のとおりです。
btndom.detachevent( "onclick"、function(){
アラート(「私もクリックしてください!」);
});
それを実行するとき、結果は非常に深刻であり、私たちは混乱しています。 2回目のクリックは削除されませんでした。どうしたの?イベントを削除するには、イベントを追加するなどのパラメーターを渡す必要があると前に述べました。ただし、JavaScriptの匿名関数では、2つの匿名関数のコードがまったく同じであっても、JavaScriptは異なる変数を使用して内部に保存します。その結果、私たちが見る現象はクリックイベントを削除できないため、コードを次のように記述する必要があります。
コードコピーは次のとおりです。
var ftn = function(){
アラート(「私もクリックしてください!」);
};
btndom.attachevent( "onclick"、ftn);
btndom.detachevent( "onclick"、ftn);
この方法で削除されたメソッドが追加され、メソッドが同じオブジェクトを指しているため、イベントは正常に削除されました。ここでのシナリオは、オペレーションを独立して定義する必要があり、匿名関数を習慣として使用しないでください。
次はDOM2イベント処理です。その原則は次の図に示されています。
DOM2は標準化されたイベントです。 DOM2イベントを使用すると、イベント配信は、キャプチャメソッド、つまりドキュメントから、次に本体に始まります。 DIVは仲介ポイントです。イベントが仲介ポイントに到達すると、イベントはターゲット段階にあります。イベントがターゲットステージに入ると、イベントが泡立ち始めて処理し始め、最終的にイベントはドキュメントで終了します。 (この記事では文書化することを指摘していますが、実際の状況は、一部のブラウザがイベントをキャプチャし始め、ウィンドウのバブルを終了することです。しかし、開発中にブラウザ自体がどのように設定されていても、ドキュメントに注意を払うことがより開発指向であるため、ここでドキュメントを使用していると思います)。主にバブルイベントが開発でより広く使用されているため、人々はバブルの一部としてターゲット段階を分類するために使用されます。
DOM2イベント処理は非常に困難です。各イベントがトリガーされると、すべての要素が2回横断されます。 IEイベントと比較して、パフォーマンスはIEイベントよりもはるかに悪いです。私は泡立っているだけなので、一度は通過するだけです。ただし、トラバーサルが少ないため、IEイベントシステムがより効率的であることを意味しません。 2つのイベントシステムを同時にサポートすることで、開発と設計の観点から、開発により柔軟性が高まります。この観点から、Dom2イベントは依然として非常に望ましいです。 DOM2イベントのコードは次のとおりです。
コードコピーは次のとおりです。
var btndom = document.getElementById( "btn");
btndom.addeventlistener( "click"、function(){
アラート( "Click Me!");
}、間違い);
var ftn = function(){
アラート(「私もクリックしてください!」);
};
btndom.addeventlistener( "click"、ftn、false);
DOM2イベント処理でのイベントの追加は、IEイベント処理よりも1つのパラメーターを受信するAddEventListenerを使用します。最初の2つは、IEイベント処理方法の2つのパラメーターと同じことを意味します。唯一の違いは、上の接頭辞が最初のパラメーターで削除され、3番目のパラメーターがブール値であることです。その値が当てはまる場合、イベントはキャプチャモードで処理され、値がfalseされます。イベントはバブルで処理されます。 3番目のパラメーターを使用すると、イベント要素をDOM2イベント処理で2回実行する理由を理解できます。目的は、2つのイベントモデルと互換性があることです。ただし、ここでは、キャプチャまたはバブルを選択しても、2つのトラバーサルが永久に実行されることに注意してください。 1つのイベント処理方法を選択した場合、他のイベント処理プロセスではイベント処理機能はトリガーされません。これは、ニュートラルギアで車をアイドリングするという原則と同じです。 DOM2イベントメソッドの設計により、DOM2イベントは実行時に2つのイベント処理方法のいずれかを実行できることを知っています。 2つのイベントストリームシステムが同時に誘発することは不可能です。したがって、要素は2回通過しますが、イベント関数を2回誘発することはできません。私は、イベント関数を指す2回の誘発はないことを意味することに注意してください。実際、次のコードなど、2つのイベントストリームモデルが同時に実行される状況をシミュレートできます。
コードコピーは次のとおりです。
btndom.addeventlistener( "click"、ftn、true);
btndom.addeventlistener( "click"、ftn、false);
しかし、この書き方はマルチイベント処理です。これは、ボタンを2回クリックするのと同等です。
Dom2は、イベントを削除する関数も提供します。この関数は、次のように書かれたremoveEventListenerです。
コードコピーは次のとおりです。
btndom.removeeventlistener( "click"、ftn、false);
IEイベントにも同じことが言えます。つまり、パラメーターはイベントを定義するパラメーターと一致する必要があります。ただし、removeEventListenerを使用する場合、3番目のパラメーターは渡されません。デフォルトは、3番目のパラメーターが渡されない場合にデフォルトがfalseであるため、バブルイベントを削除することです。例えば:
コードコピーは次のとおりです。
btndom.addeventlistener( "click"、ftn、true);
btndom.removeeventlistener( "click"、ftn);
実行して、イベントが正常に削除されていないことがわかります。
最後に、IE9以下を含むIE9ではDOM2イベントの取り扱いはIE9で十分にサポートされていると言いたいと思います。以下はDOM2イベントをサポートしていません。
以下の3つのイベント方法を次のように比較しましょう。
比較1:片側と他の2つの方法の1つの方法の比較
方法1を書き込む方法は、HTMLとJavaScriptを組み合わせることです。あなたには私がいて、私にはあなたがいます。この方法を深めて、HTMLとJavaScriptの混合開発を実現します。ソフトウェア用語では、コードカップリングです。コードの結合は良くなく、非常に悪いです。これはルーキープログラマーのレベルであるため、方法が完全に敗北すると、他の2つの方法が勝ちます。
比較2:方法2および方法3
それらの2つは同じように書かれています。誰が良くも悪いているかを言うのは本当に難しい場合があります。上記のコンテンツを見ると、モード2とモード3の最大の違いは、DOM要素に1つのイベントしかなく、1回だけであることがわかったのですが、モード3では、DOM要素のイベントが複数のイベント処理機能を持つことができることがわかりました。 DOM2イベント処理では、モード3を使用すると、イベントフロー方法を正確に制御できます。したがって、モード3の関数はモード2よりも強力であるため、モード3と比較してわずかに優れています。
以下は、この記事の焦点です。イベントシステムのパフォーマンスの問題。パフォーマンスの問題を解決するには、焦点を見つける必要があります。ここでは、2つのフォーカスポイントからのイベントシステムのパフォーマンスの問題について考えます。つまり、トラバーサルの数とメモリ消費の数を減らすことです。
まず、トラバーサルの数。イベントストリームをキャプチャしたり、イベントストリームを泡立てたりするかどうかにかかわらず、それらは要素を通過しますが、それらはすべて上部ウィンドウまたはドキュメントから始まるトラバーサルをすべて通過します。ページのDOM要素が深い親子関係を持っている場合、あなたが通過する要素が多いほど、DOM2イベント処理のように、トラバーサルが大きくなります。このイベントストリームのトラバーサルの問題を解決する方法は?私の答えはノーです。ここにいる友人の中には質問があるかもしれませんが、どうしてもういないのですか?イベントシステムにはイベントオブジェクトがあります。これはイベントです。このオブジェクトには、イベントを防止したり、キャプチャしたりする方法があります。なぜ私は誰もいないと言うのですか?この友人の質問は理にかなっていますが、この方法を使用して横断を減らしたい場合、私たちのコードは父と息子の要素と祖父の要素の関係との関係に対処します。ページ要素がたくさんネストされている場合、これは完了できないタスクであるため、私の答えは、トラバーサルの問題を変更できず、適応することができるということです。
トラバーサルを減らすことはイベントシステムのパフォーマンスの問題を解決できないようであるため、メモリ消費のみを検討できるようになりました。 C#は非常に便利だと人々が言うのをよく聞きますが、Webフロントエンドの開発にはさらに良いことです。ボタンをC#IDEのページに直接ドラッグできます。ボタンがページに到達すると、JavaScriptコードがボタンにイベントを自動的に追加します。もちろん、内部のイベント関数は空の関数です。したがって、このようにページに100個のボタンを配置できると思います。単一のコードが機能しない場合、100個のボタンイベント処理があります。これは非常に便利です。最後に、ボタンの1つに特定のボタンイベントを追加して、ページを実行します。このページは効率的ですか? JavaScriptでは、各関数はオブジェクトであり、各オブジェクトはメモリを消費するため、この役に立たない99イベント関数コードは、多くの価値のあるブラウザメモリを消費する必要があります。もちろん、実際の開発環境ではこれを行いませんが、Ajaxの時代に人気のあるシングルページ開発の時代にはクレイジーで人気があります。これは、Webページに非常に多くのイベントがあります。つまり、各イベントにはイベント機能がありますが、すべての操作は1つのイベントのみをトリガーします。この時点で、他のイベントは横になっている間眠っていますが、それは役割を果たさず、コンピューターのメモリを消費します。
この状況を変えるためのソリューションが必要であり、実際にはそのような解決策があります。この計画を明確に説明するために、最初に背景知識を追加したいと思います。 DOM2イベント処理の議論で、ターゲットオブジェクトの概念について言及しました。 DOM2イベント処理方法は別として、キャプチャイベント処理とバブルイベント処理にターゲットオブジェクトの概念もあります。ターゲットオブジェクトは、イベントの特定の操作のDOM要素です。たとえば、クリックボタン操作のボタンはターゲットオブジェクトです。イベント処理方法に関係なく、イベント関数にはイベントオブジェクトが含まれます。イベントオブジェクトには属性ターゲットがあり、ターゲットは常にターゲットオブジェクトを指し、イベントオブジェクトには、キャプチャまたはバブルイベントに流れるDOM要素を指す別の属性であるCurrentTargetがあります。上記の説明から、それがキャプチャイベントであろうとバブルイベントであろうと、イベントフローがドキュメントに流れることがわかります。ドキュメントにクリックイベントを追加し、ページのボタンがクリックイベントを追加しない場合、ボタンをクリックすると、ドキュメントのクリックイベントがトリガーされることがわかります。ここには、ドキュメントクリックイベントがトリガーされると、イベントターゲットのターゲットがドキュメントではなくボタンであるため、次のようなコードを書くことができるという詳細があります。
コードコピーは次のとおりです。
<入力型= "button" id = "btn" name = "btn" value = "button"/>
<a href = "#" id = "aa"> aa </a>
document.addeventlistener( "click"、function(evt){
var target = evt.target;
switch(target.id){
ケース「BTN」:
alert( "button");
壊す;
ケース「AA」:
アラート( "a");
壊す;
}
}、間違い);
実行して、効果はボタンを個別に書いたイベントと同じであることがわかりました。しかし、その利点は自明です。 1つの関数はページ全体のイベント関数を処理し、イベント関数はアイドル状態ではなく、完璧です。この計画には、イベント代表団の職業名もあります。 jQueryの代表法は、この原則に従って行われます。実際、イベント委任の効率は、イベント機能の削減に反映されているだけでなく、DOMトラバーサル操作を削減します。たとえば、上記の例では、ドキュメントに関数を追加します。ドキュメントはページ上のトップレベルのオブジェクトであり、読み取り効率は非常に高いです。特定のオブジェクトイベントに関しては、DOM操作を使用せず、イベントオブジェクトのターゲット属性を使用します。これはすべて、1つの文でのみ要約できます。それは非常に高速で、速い理由はありません。
イベント委任は、私たちに大きな副産物をもたらすこともできます。 jQueryを使用した友人は、ライブ方法を使用する必要がありました。ライブメソッドの機能は、ページ要素にイベント操作を追加できることです。この要素が現在ページに存在しなくても、イベントを追加できます。イベント委任メカニズムを理解した後、ライブの原則は理解しやすいです。実際、jQueryのライブはイベント代表団を通じて行われ、ライブはイベントを追加する効率的な方法でもあります。
イベント委任を理解した後、jQueryのバインド法は非効率的な方法であることがわかります。元のイベント定義方法を使用するため、Bindを使用する必要があります。実際、jQueryの開発者もこの問題に気づいています。 jQueryの新しいバージョンには、onメソッドがあります。 ONメソッドには、バインド、ライブ、および委任メソッドのすべての関数が含まれています。したがって、この記事を読んだ友人は、イベントを追加し、機能を使用してイベントを追加するという以前の方法を放棄する必要があることをお勧めします。
イベント委任には別の利点があります。上記の記事のイベント委任の例では、ドキュメントにイベントを追加しました。ここで比較したいです。 jQueryでは、以下に示すように、DOM Elementイベントの定義をReady Methodに配置することに慣れています。
コードコピーは次のとおりです。
$(document).ready(function(){
xxx.bind( "click"、function(){});
});
Ready関数は、ページDOMドキュメントがロードされた後に実行されます。オンロード関数よりも最初に実行されます。これには事前に多くの利点があります。利点の1つは、パフォーマンスを向上させることです。 jQueryのようなイベントの定義も標準的な慣行です。一部の友人は、Ready以外の特定のイベントをバインドしなければならず、最後にボタンが無効になることを発見しなければならないと思います。この無効なシナリオにはしばらく時間がかかることがあり、しばらくすると大丈夫です。したがって、私たちはしばしばこの問題の原則を無視し、準備が整った関数のイベントに結合しません。この操作は、実際にはDOMがロードされる前の拘束力のあるイベントであり、この期間の間に、実際にイベントをそれらに結合します。 、いくつかの要素がページ上に構築されていない可能性が非常に高いため、イベントのバインディングは無効になります。したがって、イベントを定義する準備ができた理由は、ページのすべての要素がロードされてロードされた後にDOM要素のイベントを定義するようにロードされることです。ただし、イベントデリゲートを使用する場合、問題は回避できます。たとえば、イベントをドキュメントにバインディングすると、ドキュメントはページ全体を表しているため、ロードするのは早い時期です。したがって、ドキュメントでイベント代表を達成することは困難であり、ブラウザに「XXX関数未定義」を報告することも困難です。この機能を要約するには、イベントデリゲートコードをページロードの任意の段階で実行できます。これにより、開発者はWebページのパフォーマンスの改善やWebページ効果の向上に自由になります。
わかりました、この記事は書かれています。おやすみ。