摘要:上一篇文章介紹了這個工具庫中的第二個依賴,這個工具庫主要完成了一個簡易的事件訂閱發(fā)布器。節(jié)點事件綁定判斷一個元素是否是節(jié)點,是通過構(gòu)造函數(shù)和屬性來判斷的。
上一篇文章介紹了clipboard.js這個工具庫中的第二個依賴tiny-emitter,這個工具庫主要完成了一個簡易的事件訂閱發(fā)布器。這次介紹一下clipboard.js源碼中的最后一個依賴的輕型工具庫good-listener,這個工具庫主要用來對dom的事件綁定進行一層封裝,支持事件委托delegate,和jquery的寫法非常類似,源碼簡潔且清晰易懂,對理解事件綁定模型和原理非常有幫助。
快速用法const listen = require("good-listener")
good-listener支持常見的三種方式來綁定事件
node節(jié)點事件綁定
var logo = document.getElementById("logo"); listen(logo, "click", function(e) { console.log(e); });
nodeList多個節(jié)點遍歷事件綁定
var anchors = document.querySelectorAll("a"); listen(anchors, "click", function(e) { console.log(e); });
字符串形式的委托事件綁定(默認委托的對象document.body)
listen(".btn", "click", function(e) { console.log(e); });代碼實現(xiàn)
good-listener的實現(xiàn)大致如下
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節(jié)點的實現(xiàn)比較簡單,一筆帶過,這里主要分析一下delegate委托的實現(xiàn)。
node節(jié)點事件綁定判斷一個元素是否是node節(jié)點,是通過構(gòu)造函數(shù)constructor和nodeType屬性來判斷的。
value !== undefined && value instanceof HTMLElement && value.nodeType === 1;
listenNode實現(xiàn),返回了一個對象,為事件綁定擴展了一個取消綁定的方法destroy
function listenNode(node, type, callback) { node.addEventListener(type, callback); return { destroy: function() { node.removeEventListener(type, callback); } } }nodeList多個節(jié)點遍歷事件綁定
判斷一個元素是否是nodeList節(jié)點,是通過構(gòu)造函數(shù)constructor和length屬性來判斷的。且需要保證類數(shù)組中的元素都是有效的dom節(jié)點
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實現(xiàn), 遍歷一下類數(shù)組,一次執(zhí)行事件綁定即可
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); }); } } }事件委托的實現(xiàn)
簡單回顧一下事件委托,比如有以下場景
1
2
3
4
需要把p標簽的點擊事件委托到父元素div上面,jquery中的寫法是
$(".wrapper").on("click", ".delegate", function(e) {...})
如果我們自己去實現(xiàn),是不能單純的去判斷點擊的target是不是包含delegate,因為點擊的元素有可能是子元素span,所以子元素可以通過冒泡找到delegate,那么委托也是應該可以觸發(fā)的。
再介紹一個方法,下面要用到,Element的原型上有一個matches方法,接受一個selector字符串,如果element元素被指定的字符串選擇,那么返回true.
1.首先來模擬這個冒泡的過程
// document節(jié)點 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 } }
這個函數(shù)就是判斷點擊的元素是否能夠向上冒泡(不斷的獲取父元素)匹配到指定的委托元素。
結(jié)合上面例子就是span能否向上找到delegate
2.使用代理模式為事件的回調(diào)函數(shù)封裝一層判斷邏輯,當符合委托邏輯的時候,才去執(zhí)行回調(diào)函數(shù)
并且為event對象添加一個屬性delegateTarget,這樣在event中可以拿到對應的三個對象
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內(nèi)部封裝
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
分為兩種情況,被委托可以是一個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) }) }結(jié)語
本次介紹的good-listener這個工具庫的用法和源碼分析,介紹了node,nodeList的事件綁定封裝的實現(xiàn),尤其探求了一下委托的實現(xiàn)方法,用不多的代碼實現(xiàn)了兼容性很好的delegate,至此clipboard.js的依賴都介紹完了,下一篇文章會整合代碼,將完整的clipboard.js實現(xiàn)展現(xiàn)出來。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/93188.html
摘要:下面對它的實現(xiàn)一一分析。可以使用獲取選中的內(nèi)容也可以使用獲取一個用戶選擇的范圍。在這里完成了對用戶選中內(nèi)容的一些操作,而且在不是表單無法觸發(fā)事件的時候,也可以在指定區(qū)域監(jiān)聽事件來實時獲取選中的內(nèi)容完成復制等功能。 項目中用到了選中復制功能 showImg(https://segmentfault.com/img/bVY7dH?w=400&h=78); 就是點擊按鈕,復制左側(cè)的內(nèi)容到剪切...
摘要:用于在同一主模塊下的不同子模塊以及不同主模塊之間的通信,支持動態(tài)綁定作用域。如果用過的父子組件事件通信以及,對事件管理器應該不會陌生的。而且支持指定作用域,可以遠程調(diào)用任意模塊的函數(shù)。 上一篇文章介紹了clipboard.js這個工具庫中的第一個依賴select這個工具庫主要完成了對任意DOM元素的復制到粘貼板的功能。這次介紹一下clipboard.js源碼中的第二個依賴的輕型工具庫t...
摘要:需求開發(fā)過程中遇到的需求需要復制請求過來的一段密令類似支付寶淘寶口令到剪切板。網(wǎng)上搜了下,是個相對比較靠譜的第三方。感謝大佬的評論意見使用該方法,會在下次更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的。 需求 開發(fā)過程中遇到的需求需要復制 請求過來的一段密令(類似支付寶淘寶口令)到剪切板。 pc端的文本復制到剪切板 如果是在pc端的話,可以直接使用原生js進...
摘要:需求開發(fā)過程中遇到的需求需要復制請求過來的一段密令類似支付寶淘寶口令到剪切板。網(wǎng)上搜了下,是個相對比較靠譜的第三方。感謝大佬的評論意見使用該方法,會在下次更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的。 需求 開發(fā)過程中遇到的需求需要復制 請求過來的一段密令(類似支付寶淘寶口令)到剪切板。 pc端的文本復制到剪切板 如果是在pc端的話,可以直接使用原生js進...
閱讀 2569·2021-11-23 09:51
閱讀 2481·2021-09-30 09:48
閱讀 1076·2021-09-10 10:51
閱讀 2213·2021-08-12 13:22
閱讀 3568·2021-08-11 10:24
閱讀 2166·2019-08-30 15:55
閱讀 646·2019-08-30 14:05
閱讀 3211·2019-08-30 13:03