今回は、Web開発におけるイベント処理のルールと、Web開発におけるイベント処理の注意事項について、実際の事例を交えて見ていきましょう。
イベント処理
イベントがトリガーされると、イベント object (イベント オブジェクト) がコールバック パラメーターとしてイベント ハンドラーに渡されることがわかっています。例:
// 不好的写法function handleClick(event) { var pop = document .getElementById('popup'); popup.style.left = event.clientX + 'px'; popup.style.top = event.clientY + 'px'; popup.className = 'reveal'; }// 你应该明白addListener函数的意思addListener(element, 'click', handleClick);
このコードは、イベント オブジェクト: clientX および clientY。これら 2 つの属性を使用して、ページに要素を表示する前に要素を配置します。このコードは非常に単純で問題がないように見えますが、このアプローチには制限があるため、実際には不適切な記述です。
ルール 1: アプリケーション ロジックを分離する
上記のコード例の最初の問題は、イベント ハンドラーにアプリケーション ロジックが含まれていることです。アプリケーション ロジックは、ユーザー 行動 ではなく、アプリケーションに関連する機能コードです。上記のコード例のアプリケーション ロジックは、特定の場所にポップアップ ボックスを表示することです。このインタラクションはユーザーが特定の要素をクリックしたときに発生するはずですが、常にそうであるとは限りません。
同じロジック部分が他の場所でトリガーされる可能性があるため、アプリケーション ロジックをすべてのイベント ハンドラーから分離することがベスト プラクティスです。たとえば、ユーザーが要素の上にマウスを移動したときにポップアップ ボックスを表示するかどうかを決定したり、キーボードの特定のキーが押されたときに同じ論理的判断を行う必要がある場合があります。このように、複数のイベント ハンドラーが同じロジックを実行しますが、コードは誤って複数回コピーされます。
イベント ハンドラーにアプリケーション ロジックを配置することのもう 1 つの欠点は、テストに関連しています。テストするときは、要素のクリックをシミュレートするのではなく、関数コードを直接トリガーする必要があります。アプリケーション ロジックがイベント ハンドラーに配置されている場合、それをテストする唯一の方法は、イベントを発生させることです。一部のテスト フレームワークではイベントのトリガーをシミュレートできますが、実際には、これはテストへの最良のアプローチではありません。関数コードを呼び出す最良の方法は、単一の関数呼び出しを使用することです。
アプリケーション ロジックとイベント処理コードを常に分離する必要があります。前述のコード例をリファクタリングする場合、最初のステップは、ポップアップ ボックスのロジックを処理するコードを別の関数に入れることです。この関数は、アプリケーションに定義されたグローバル オブジェクトにマウントされる可能性があります。イベント ハンドラーは常に同じグローバル オブジェクト内に存在する必要があるため、2 つのメソッドがあります。
// 好的写法 - 拆分应用逻辑var MyApplication = { handleClick: function (event) { this.showPopup(event); }, showPopup: function (event) { var pop = document.getElementById('popup'); popup.style.left = event.clientX + 'px'; popup.style.top = event.clientY + 'px'; popup.className = 'reveal'; } }; addListener(element, 'click', function (event) { MyApplication.handleClick(event); });
これまでイベント ハンドラーに含まれていたすべてのアプリケーション ロジックは、MyApplication.showPopup() メソッドに移動されました。現在、MyApplication.handleClick() メソッドは、MyApplication.showPopup() を呼び出すという 1 つのことだけを実行します。アプリケーション ロジックが取り除かれると、同じ機能コードへの呼び出しが複数のポイントで発生する可能性があり、特定のイベントのトリガーに依存する必要がなくなり、明らかに便利になります。ただし、これはイベント ハンドラー コードを分解するための最初のステップにすぎません。
ルール 2: イベント オブジェクトを配布しない
アプリケーション ロジックを削除した後も、上記のコード例には問題がまだ残っています。つまり、イベント オブジェクトが制御不能に配布されます。匿名イベント ハンドラーから MyApplication.handleClick() を渡し、匿名イベント ハンドラーはそれを MyApplication.showPopup() に渡します。前述したように、イベント オブジェクトにはイベントに関連する多くの追加情報が含まれており、このコードではそのうちの 2 つだけを使用します。アプリケーション ロジックは、次の理由により、関数を正しく完了するためにイベント オブジェクトに依存すべきではありません:
メソッド インターフェイスは、どのデータが必要であるかを示しません。優れた API は、期待と依存関係について透過的でなければなりません。イベント オブジェクトをパラメーターとして取得しても、イベントのどのプロパティが役立つのか、またそれらが何に使用されるのかがわかりません
したがって、このメソッドをテストしたい場合は、イベント オブジェクトを再作成してパラメーターとして渡す必要があります。 。したがって、テスト コードを正しく作成するには、このメソッドがどのような情報を使用するかを正確に知る必要があります。
これらの問題 (不明瞭なインターフェイス形式やテスト用の自己構築イベント オブジェクトを指す) は、大規模な Web アプリケーションではお勧めできません。コードが明確でないとバグが発生する可能性があります。
最善の方法は、イベント ハンドラーにイベント オブジェクトを使用してイベントを処理させ、必要なデータをすべて取得してアプリケーション ロジックに渡すことです。たとえば、MyApplication.showPopup() メソッドには、x 座標と y 座標の 2 つのデータのみが必要です。このようにして、これら 2 つのパラメーターを受け取るようにメソッドを書き直します。
// 好的写法var MyApplication = { handleClick: function (event) { this.showPopup(event.clientX, event.clientY); }, showPopup: function (x, y) { var pop = document.getElementById('popup'); popup.style.left = x + 'px'; popup.style.top = y + 'px'; popup.className = 'reveal'; } }; addListener(element, 'click', function (event) { MyApplication.handleClick(event); });
在这段新重写的代码中,MyApplication.handleClick()将x坐标和y坐标传入了MyApplication.showPopup(),代替了之前传入的事件对象。可以很清晰地看到MyApplication.showPopup()所期望传入的参数,并且在测试或代码的任意位置都可以很轻易地直接调用这段逻辑,比如:
// 这样调用非常棒MyApplication.showPopup(10, 10);
当处理事件时,最好让事件处理程序成为接触到event对象的唯一的函数。事件处理程序应当在进入应用逻辑之前针对event对象执行任何必要的操作,包括阻止默认事件或阻止事件冒泡,都应当直接包含在事件处理程序中。比如:
// 好的写法var MyApplication = { handleClick: function (event) { // 假设事件支持DOM Level2 event.preventDefault(); event.stopPropagation(); // 传入应用逻辑 this.showPopup(event.clientX, event.clientY); }, showPopup: function (x, y) { var pop = document.getElementById('popup'); popup.style.left = x + 'px'; popup.style.top = y + 'px'; popup.className = 'reveal'; } }; addListener(element, 'click', function (event) { MyApplication.handleClick(event); });
在这段代码中,MyApplication.handleClick()是事件处理程序,因此它在将数据传入应用逻辑之前调用了event.preventDefault()和event.stopPropagation(),这清除地展示了事件处理程序和应用逻辑之间的分工。因为应用逻辑不需要对event产生依赖,进而在很多地方都可以轻松地使用相同的业务逻辑,包括写测试代码。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がWeb開発におけるイベント処理ルールとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。