私は、この関数のソースを見ていないが、私は疑問に思う、それはこのように動作しない:それらへjQuery.on()はどのように機能しますか?
- 選択要素(複数可)そのselecotrsによって
- 代表提供するイベント・ハンドラを
- そのセレクタと常に非委任するに
setInterval
を実行し、すべての
私は、この関数のソースを見ていないが、私は疑問に思う、それはこのように動作しない:それらへjQuery.on()はどのように機能しますか?
setInterval
を実行し、すべての
Event Delegationバージョンの.on
についての質問です。
JavaScriptでは、ほとんどのイベントはDOM階層でbubbleです。つまり、ある要素に対してバブル可能なイベントが発生すると、レベルがdocument
までDOMにバブルアップします。
<div>
<span>1</span>
<span>2</span>
</div>
今、私たちはイベントの委任を適用します:
は、この基本的なマークアップを検討し
$('div').on('click', 'span', fn);
イベントハンドラはdiv
要素にのみ装着されています。 span
はdiv
の内部にあるため、スパンのクリックはdiv
までバブルし、div
のクリックハンドラを起動します。その時点で、event.target
(またはターゲットとdelegateTarget
の間の要素のいずれか)が委任先セレクタと一致するかどうかを確認するだけです。
のは、少し複雑にしてみましょう:次のように
<div id="parent">
<span>1</span>
<span>2 <b>another nested element inside span</b></span>
<p>paragraph won't fire delegated handler</p>
</div>
基本的なロジックは以下のとおりです。
//attach handler to an ancestor
document.getElementById('parent').addEventListener('click', function(e) {
//filter out the event target
if (e.target.tagName.toLowerCase() === 'span') {
console.log('span inside parent clicked');
}
});
event.target
があなたのフィルター内にネストされたときに上記が一致しませんが。 jQueryの.on
はないとしてだけ子孫要素に一致するように更新されたコード:
document.getElementById('parent').addEventListener('click', function(e) {
var failsFilter = true,
el = e.target;
while (el !== this && (failsFilter = el.tagName.toLowerCase() !== 'span') && (el = el.parentNode));
if (!failsFilter) {
console.log('span inside parent clicked');
}
});
編集:私たちは、いくつかの反復ロジックが必要です。
注:これらのスニペットは説明のためのものであり、実際の世界では使用されません。もちろん、古いIEをサポートする予定がない場合を除きます。古いIEでは、addEventListener
/attachEvent
と同様にevent.target || event.srcElement
のテスト機能が必要になります。イベントオブジェクトがハンドラ関数に渡されるかグローバルスコープで使用可能になるかをチェックするなどのいくつかの癖があります。ありがたいことに、jQueryはすべてのことをシームレスにバックグラウンドで行います。=]
Necromancing:念の誰で
は/バニラ、JavaScriptで暮らす上でのjQueryを交換する必要があります。
活字体:
/// attach an event handler, now or in the future,
/// for all elements which match childselector,
/// within the child tree of the element maching parentSelector.
export function subscribeEvent(parentSelector: string | Element
, eventName: string
, childSelector: string
, eventCallback)
{
if (parentSelector == null)
throw new ReferenceError("Parameter parentSelector is NULL");
if (childSelector == null)
throw new ReferenceError("Parameter childSelector is NULL");
// nodeToObserve: the node that will be observed for mutations
let nodeToObserve: Element = <Element>parentSelector;
if (typeof (parentSelector) === 'string')
nodeToObserve = document.querySelector(<string>parentSelector);
let eligibleChildren: NodeListOf<Element> = nodeToObserve.querySelectorAll(childSelector);
for (let i = 0; i < eligibleChildren.length; ++i)
{
eligibleChildren[i].addEventListener(eventName, eventCallback, false);
} // Next i
// https://stackoverflow.com/questions/2712136/how-do-i-make-this-loop-all-children-recursively
function allDescendants(node: Node)
{
if (node == null)
return;
for (let i = 0; i < node.childNodes.length; i++)
{
let child = node.childNodes[i];
allDescendants(child);
} // Next i
// IE 11 Polyfill
if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector;
if ((<Element>node).matches)
{
if ((<Element>node).matches(childSelector))
{
// console.log("match");
node.addEventListener(eventName, eventCallback, false);
} // End if ((<Element>node).matches(childSelector))
// else console.log("no match");
} // End if ((<Element>node).matches)
// else console.log("no matchfunction");
} // End Function allDescendants
// Callback function to execute when mutations are observed
let callback:MutationCallback = function (mutationsList: MutationRecord[], observer: MutationObserver)
{
for (let mutation of mutationsList)
{
// console.log("mutation.type", mutation.type);
// console.log("mutation", mutation);
if (mutation.type == 'childList')
{
for (let i = 0; i < mutation.addedNodes.length; ++i)
{
let thisNode: Node = mutation.addedNodes[i];
allDescendants(thisNode);
} // Next i
} // End if (mutation.type == 'childList')
// else if (mutation.type == 'attributes') { console.log('The ' + mutation.attributeName + ' attribute was modified.');
} // Next mutation
}; // End Function callback
// Options for the observer (which mutations to observe)
let config = { attributes: false, childList: true, subtree: true };
// Create an observer instance linked to the callback function
let observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(nodeToObserve, config);
} // End Function subscribeEvent
はJavaScript:
/// attach an event handler, now or in the future,
/// for all elements which match childselector,
/// within the child tree of the element maching parentSelector.
function subscribeEvent(parentSelector, eventName, childSelector, eventCallback) {
if (parentSelector == null)
throw new ReferenceError("Parameter parentSelector is NULL");
if (childSelector == null)
throw new ReferenceError("Parameter childSelector is NULL");
// nodeToObserve: the node that will be observed for mutations
var nodeToObserve = parentSelector;
if (typeof (parentSelector) === 'string')
nodeToObserve = document.querySelector(parentSelector);
var eligibleChildren = nodeToObserve.querySelectorAll(childSelector);
for (var i = 0; i < eligibleChildren.length; ++i) {
eligibleChildren[i].addEventListener(eventName, eventCallback, false);
} // Next i
// https://stackoverflow.com/questions/2712136/how-do-i-make-this-loop-all-children-recursively
function allDescendants(node) {
if (node == null)
return;
for (var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
allDescendants(child);
} // Next i
// IE 11 Polyfill
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.msMatchesSelector;
if (node.matches) {
if (node.matches(childSelector)) {
// console.log("match");
node.addEventListener(eventName, eventCallback, false);
} // End if ((<Element>node).matches(childSelector))
// else console.log("no match");
} // End if ((<Element>node).matches)
// else console.log("no matchfunction");
} // End Function allDescendants
// Callback function to execute when mutations are observed
var callback = function (mutationsList, observer) {
for (var _i = 0, mutationsList_1 = mutationsList; _i < mutationsList_1.length; _i++) {
var mutation = mutationsList_1[_i];
// console.log("mutation.type", mutation.type);
// console.log("mutation", mutation);
if (mutation.type == 'childList') {
for (var i = 0; i < mutation.addedNodes.length; ++i) {
var thisNode = mutation.addedNodes[i];
allDescendants(thisNode);
} // Next i
} // End if (mutation.type == 'childList')
// else if (mutation.type == 'attributes') { console.log('The ' + mutation.attributeName + ' attribute was modified.');
} // Next mutation
}; // End Function callback
// Options for the observer (which mutations to observe)
var config = { attributes: false, childList: true, subtree: true };
// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(nodeToObserve, config);
} // End Function subscribeEvent
だけでなく、それはすべてOKですjQueryとjQuery.on()の使い方について、私は興味がありますJavaScriptとDOMだけで同様のスニペットを書くことが可能ですか? –
@Zlatanはい、そうです。そんなことはありませんが、多くの派手な委任セレクタはありません。私は純粋なJSの1つの例を追加します。 –
OK。さて、あなたは 'document.querySelector()'や 'document.querySelectorAll()')を使って例を書くことができると思います: –