clipboard.jsコード分析(3)-good-listener
6495 ワード
前の記事ではclipboardを紹介しました.jsというツールライブラリの2番目の依存tiny-emitterは、主に簡易なイベントサブスクリプションパブリッシャを完了しています.今回は、
クイック使用法 を巡回する.文字列形式の委任イベントバインド(デフォルトの委任オブジェクト
コード実装
Nodeノードイベントバインド
1つの要素が
NodeList複数ノードループイベントバインド
1つの要素が
イベント依頼の実現
イベント依頼を簡単に振り返ります.例えば、次のようなシーンがあります.
私たち自身が実現すれば、クリックした
さらに、
1.まずこの泡立ちの過程をシミュレートする
この関数は,クリックした要素が指定した委任要素に上向きに泡を立てることができるかどうかを判断するものである.上記の例を組み合わせると
2.エージェントモードを使用してイベントのコールバック関数に1層の判断ロジックをカプセル化し、依頼ロジックに合致した場合、コールバック関数を実行し、 である. である. である.
3.delegate内部パッケージ
4.delegateは2つのケースに分けられ、委任された要素は
別々に処理すればよい
締めくくり
今回紹介した
clipboard.js
のソースコードの最後に依存する軽量ツールライブラリgood-listenerを紹介します.このツールライブラリは主にdom
のイベントバインドをカプセル化し、イベント依頼delegate
をサポートします.jquery
の書き方とよく似ています.ソースコードは簡潔で分かりやすく、イベントバインドモデルと原理を理解するのに役立ちます.クイック使用法
const listen = require('good-listener')
good-listener
は、イベントをバインドするための一般的な3つの方法をサポートします.node
ノードイベントバインドvar logo = document.getElementById('logo');
listen(logo, 'click', function(e) {
console.log(e);
});
nodeList
複数のノードがイベントバインディングvar anchors = document.querySelectorAll('a');
listen(anchors, 'click', function(e) {
console.log(e);
});
document.body
)listen('.btn', 'click', function(e) {
console.log(e);
});
コード実装
good-listener
の実現は概ね以下の通りである.function listen(target, type, callback) {
if (is.node(target)) {
return listenNode(target, type, callback);
} else if (is.nodeList(target)) {
return listenNodeList(target, type, callback);
} else if (is.string(target)) {
return listenSelector(target, type, callback);
} else {
throw new TypeError(`argument must be a
String, HTMLElement, HTMLCollection, or NodeList`);
}
}
node
およびnodeList
ノードの実装は比較的簡単であり,ここでは主にdelegate
委託の実装を分析する.Nodeノードイベントバインド
1つの要素が
node
ノードであるか否かを判断するには、構造関数constructor
およびnodeType
の属性によって判断される.value !== undefined && value instanceof HTMLElement && value.nodeType === 1;
listenNode
が実装され、オブジェクトが返され、イベントバインドにバインド解除方法destroy
が拡張されるfunction listenNode(node, type, callback) {
node.addEventListener(type, callback);
return {
destroy: function() {
node.removeEventListener(type, callback);
}
}
}
NodeList複数ノードループイベントバインド
1つの要素が
nodeList
ノードであるか否かを判断するには、構造関数constructor
およびlength
の属性によって判断される.クラス配列の要素が有効なdom
ノードであることを保証する必要があるvar type = Object.prototype.toString.call(value)
value !== undefined &&
(type === '[object NodeList]' || type === '[object HTMLCollection]') &&
('length' in value) &&
(value.length === 0 || exports.node(value[0]))
listenNodeList
実装、クラス配列を遍歴し、イベントバインドを一度に実行すればよいfunction listenNodeList(nodeList, type, callback) {
Array.prototype.forEach.call(nodeList, function(node) {
node.addEventListener(type, callback);
});
return {
destroy: function() {
Array.prototype.forEach.call(nodeList, function(node) {
node.removeEventListener(type, callback);
});
}
}
}
イベント依頼の実現
イベント依頼を簡単に振り返ります.例えば、次のようなシーンがあります.
1
2
3
4
p
タグのクリックイベントを親要素div
に依頼する必要があります.jquery
の書き方は$('.wrapper').on('click', '.delegate', function(e) {...})
私たち自身が実現すれば、クリックした
target
がdelegate
を含むかどうかを単純に判断することはできません.クリックした要素はサブ要素span
である可能性があるので、サブ要素は泡を立ててdelegate
を見つけることができます.依頼もトリガーできるはずです.さらに、
Element
のプロトタイプには、selector
の文字列を受け入れるmatchesメソッドがあり、element
の要素が指定する文字列が選択されると、true
に戻る.1.まずこの泡立ちの過程をシミュレートする
// document
const DOCUMENT_NODE_TYPE = 9
function closet (element, selector) {
while(element && element.nodeType !== DOCUMENT_NODE_TYPE) {
if (typeof element.matches === 'function' && element.matches(selector)) {
return element
}
element = element.parentNode
}
}
この関数は,クリックした要素が指定した委任要素に上向きに泡を立てることができるかどうかを判断するものである.上記の例を組み合わせると
span
がdelegate
を上に見つけることができるかどうかです.2.エージェントモードを使用してイベントのコールバック関数に1層の判断ロジックをカプセル化し、依頼ロジックに合致した場合、コールバック関数を実行し、
event
オブジェクトに属性delegateTarget
を追加し、event
で対応する3つのオブジェクトを取得することができる.this
およびe.currentTarget
は、委任要素e.delegateTarget
は、委任要素e.target
はクリック要素function listener(element, selector, type, callback) {
return function(e) {
e.delegateTarget = closest(e.target, selector);
if (e.delegateTarget) {
callback.call(element, e);
}
}
}
3.delegate内部パッケージ
let _delegate = (element, selector, type, callback, useCapture) => {
// element selector
let listenerFn = listener.apply(this, arguments)
element.addEventListener(type, listenerFn, useCapture)
return {
destroy () {
element.removeListener(type, listenerFn, useCapture)
}
}
}
4.delegateは2つのケースに分けられ、委任された要素は
dom
要素であってもよいし、css
セレクタ文字列であってもよい.以下に示すようにdelegate(document.body, '.btn', 'click', function(e) {
console.log(e.delegateTarget);
}, false);
delegate('.container', '.btn', 'click', function(e) {
console.log(e.delegateTarget);
}, false);
別々に処理すればよい
let delegate = (elements, selector, type, callback, useCapture) => {
if (typeof elements.addEventListener === 'function') {
return _delegate.apply(null, arguments)
}
if (typeof elements === 'string') {
elements = document.querySelectorAll(elements)
}
return Array.prototype.map.call(elements, function (element) {
return _delegate(element, selector, type, callback, useCapture)
})
}
締めくくり
今回紹介した
good-listener
というツールライブラリの使い方とソースコード分析では、node
nodeList
のイベントバインドパッケージの実装を紹介し、特に
の実装方法を探求し、少ないコードで互換性の良いdelegate
を実現しました.これでclipboard.js
の依存はすべて紹介され、次の文章ではコードを統合します.完全なclipboard.js
の実装を示します.