亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

clipboard.js代碼分析(3)- good-listener

objc94 / 1175人閱讀

摘要:上一篇文章介紹了這個(gè)工具庫(kù)中的第二個(gè)依賴,這個(gè)工具庫(kù)主要完成了一個(gè)簡(jiǎn)易的事件訂閱發(fā)布器。節(jié)點(diǎn)事件綁定判斷一個(gè)元素是否是節(jié)點(diǎn),是通過(guò)構(gòu)造函數(shù)和屬性來(lái)判斷的。

上一篇文章介紹了clipboard.js這個(gè)工具庫(kù)中的第二個(gè)依賴tiny-emitter,這個(gè)工具庫(kù)主要完成了一個(gè)簡(jiǎn)易的事件訂閱發(fā)布器。這次介紹一下clipboard.js源碼中的最后一個(gè)依賴的輕型工具庫(kù)good-listener,這個(gè)工具庫(kù)主要用來(lái)對(duì)dom的事件綁定進(jìn)行一層封裝,支持事件委托delegate,和jquery的寫(xiě)法非常類似,源碼簡(jiǎn)潔且清晰易懂,對(duì)理解事件綁定模型和原理非常有幫助。

快速用法
const listen = require("good-listener")

good-listener支持常見(jiàn)的三種方式來(lái)綁定事件

node節(jié)點(diǎn)事件綁定

var logo = document.getElementById("logo");

listen(logo, "click", function(e) {
    console.log(e);
});

nodeList多個(gè)節(jié)點(diǎn)遍歷事件綁定

var anchors = document.querySelectorAll("a");

listen(anchors, "click", function(e) {
    console.log(e);
});

字符串形式的委托事件綁定(默認(rèn)委托的對(duì)象document.body)

listen(".btn", "click", function(e) {
    console.log(e);
});
代碼實(shí)現(xiàn)

good-listener的實(shí)現(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`);
  }
}

對(duì)于nodenodeList節(jié)點(diǎn)的實(shí)現(xiàn)比較簡(jiǎn)單,一筆帶過(guò),這里主要分析一下delegate委托的實(shí)現(xiàn)。

node節(jié)點(diǎn)事件綁定

判斷一個(gè)元素是否是node節(jié)點(diǎn),是通過(guò)構(gòu)造函數(shù)constructornodeType屬性來(lái)判斷的。

value !== undefined && value instanceof HTMLElement && value.nodeType === 1;

listenNode實(shí)現(xiàn),返回了一個(gè)對(duì)象,為事件綁定擴(kuò)展了一個(gè)取消綁定的方法destroy

function listenNode(node, type, callback) {
  node.addEventListener(type, callback);

  return {
    destroy: function() {
      node.removeEventListener(type, callback);
    }
  }
}
nodeList多個(gè)節(jié)點(diǎn)遍歷事件綁定

判斷一個(gè)元素是否是nodeList節(jié)點(diǎn),是通過(guò)構(gòu)造函數(shù)constructorlength屬性來(lái)判斷的。且需要保證類數(shù)組中的元素都是有效的dom節(jié)點(diǎn)

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實(shí)現(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);
      });
    }
  }
}
事件委托的實(shí)現(xiàn)

簡(jiǎn)單回顧一下事件委托,比如有以下場(chǎng)景

1

2

3

4

需要把p標(biāo)簽的點(diǎn)擊事件委托到父元素div上面,jquery中的寫(xiě)法是

$(".wrapper").on("click", ".delegate", function(e) {...})

如果我們自己去實(shí)現(xiàn),是不能單純的去判斷點(diǎn)擊的target是不是包含delegate,因?yàn)辄c(diǎn)擊的元素有可能是子元素span,所以子元素可以通過(guò)冒泡找到delegate,那么委托也是應(yīng)該可以觸發(fā)的。

再介紹一個(gè)方法,下面要用到,Element的原型上有一個(gè)matches方法,接受一個(gè)selector字符串,如果element元素被指定的字符串選擇,那么返回true.

1.首先來(lái)模擬這個(gè)冒泡的過(guò)程

// document節(jié)點(diǎn)
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
    }
}

這個(gè)函數(shù)就是判斷點(diǎn)擊的元素是否能夠向上冒泡(不斷的獲取父元素)匹配到指定的委托元素。
結(jié)合上面例子就是span能否向上找到delegate

2.使用代理模式為事件的回調(diào)函數(shù)封裝一層判斷邏輯,當(dāng)符合委托邏輯的時(shí)候,才去執(zhí)行回調(diào)函數(shù)
并且為event對(duì)象添加一個(gè)屬性delegateTarget,這樣在event中可以拿到對(duì)應(yīng)的三個(gè)對(duì)象

thise.currentTarget 是被委托的元素

e.delegateTarget 是委托元素

e.target 是點(diǎn)擊元素

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
分為兩種情況,被委托可以是一個(gè)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é)語(yǔ)

本次介紹的good-listener這個(gè)工具庫(kù)的用法和源碼分析,介紹了node,nodeList的事件綁定封裝的實(shí)現(xiàn),尤其探求了一下委托的實(shí)現(xiàn)方法,用不多的代碼實(shí)現(xiàn)了兼容性很好的delegate,至此clipboard.js的依賴都介紹完了,下一篇文章會(huì)整合代碼,將完整的clipboard.js實(shí)現(xiàn)展現(xiàn)出來(lái)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/93188.html

相關(guān)文章

  • clipboard.js代碼分析(1)-select

    摘要:下面對(duì)它的實(shí)現(xiàn)一一分析。可以使用獲取選中的內(nèi)容也可以使用獲取一個(gè)用戶選擇的范圍。在這里完成了對(duì)用戶選中內(nèi)容的一些操作,而且在不是表單無(wú)法觸發(fā)事件的時(shí)候,也可以在指定區(qū)域監(jiān)聽(tīng)事件來(lái)實(shí)時(shí)獲取選中的內(nèi)容完成復(fù)制等功能。 項(xiàng)目中用到了選中復(fù)制功能 showImg(https://segmentfault.com/img/bVY7dH?w=400&h=78); 就是點(diǎn)擊按鈕,復(fù)制左側(cè)的內(nèi)容到剪切...

    li21 評(píng)論0 收藏0
  • clipboard.js代碼分析(2)-emitter

    摘要:用于在同一主模塊下的不同子模塊以及不同主模塊之間的通信,支持動(dòng)態(tài)綁定作用域。如果用過(guò)的父子組件事件通信以及,對(duì)事件管理器應(yīng)該不會(huì)陌生的。而且支持指定作用域,可以遠(yuǎn)程調(diào)用任意模塊的函數(shù)。 上一篇文章介紹了clipboard.js這個(gè)工具庫(kù)中的第一個(gè)依賴select這個(gè)工具庫(kù)主要完成了對(duì)任意DOM元素的復(fù)制到粘貼板的功能。這次介紹一下clipboard.js源碼中的第二個(gè)依賴的輕型工具庫(kù)t...

    MoAir 評(píng)論0 收藏0
  • 在vue移動(dòng)端項(xiàng)目中,配合clipboard.js插件,復(fù)制一段密令(類似淘寶支付寶口令)的文本到剪

    摘要:需求開(kāi)發(fā)過(guò)程中遇到的需求需要復(fù)制請(qǐng)求過(guò)來(lái)的一段密令類似支付寶淘寶口令到剪切板。網(wǎng)上搜了下,是個(gè)相對(duì)比較靠譜的第三方。感謝大佬的評(píng)論意見(jiàn)使用該方法,會(huì)在下次更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的。 需求 開(kāi)發(fā)過(guò)程中遇到的需求需要復(fù)制 請(qǐng)求過(guò)來(lái)的一段密令(類似支付寶淘寶口令)到剪切板。 pc端的文本復(fù)制到剪切板 如果是在pc端的話,可以直接使用原生js進(jìn)...

    brianway 評(píng)論0 收藏0
  • 在vue移動(dòng)端項(xiàng)目中,配合clipboard.js插件,復(fù)制一段密令(類似淘寶支付寶口令)的文本到剪

    摘要:需求開(kāi)發(fā)過(guò)程中遇到的需求需要復(fù)制請(qǐng)求過(guò)來(lái)的一段密令類似支付寶淘寶口令到剪切板。網(wǎng)上搜了下,是個(gè)相對(duì)比較靠譜的第三方。感謝大佬的評(píng)論意見(jiàn)使用該方法,會(huì)在下次更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的。 需求 開(kāi)發(fā)過(guò)程中遇到的需求需要復(fù)制 請(qǐng)求過(guò)來(lái)的一段密令(類似支付寶淘寶口令)到剪切板。 pc端的文本復(fù)制到剪切板 如果是在pc端的話,可以直接使用原生js進(jìn)...

    Lyux 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<