国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

向zepto.js學(xué)習(xí)如何手動(trigger)觸發(fā)DOM事件

Julylovin / 2280人閱讀

摘要:好啦我們已經(jīng)解決了是啥的疑問了,現(xiàn)在回去開始一步步解讀如何實(shí)現(xiàn)手動觸發(fā)事件。我們主要看看這里面幾乎含有如何手動觸發(fā)一個(gè)事件的大部分步驟和內(nèi)容。

前言

前端在最近幾年實(shí)在火爆異常,vue、react、angular各路框架層出不窮,咱們要是不知道個(gè)雙向數(shù)據(jù)綁定,不曉得啥是虛擬DOM,也許就被鄙視了?;馃岬谋澈笸彩菬o盡的浮躁,學(xué)習(xí)這些先進(jìn)流行的類庫或者框架可以讓我們走的更快,但是靜下心來回歸基礎(chǔ),把基石打牢固,卻可以讓我們走的更穩(wěn),更遠(yuǎn)。

最近一直在看zepto的源碼,希望通過學(xué)習(xí)它掌握一些框架設(shè)計(jì)的技巧,也將很久不再拾起的js基礎(chǔ)重新溫習(xí)鞏固一遍。如果你對這個(gè)系列感興趣,歡迎點(diǎn)擊下方地址watch,隨時(shí)關(guān)注動態(tài)。這篇文章主要想說一下zepto中事件模塊(event.js)的trigger實(shí)現(xiàn)原理。

原文地址

倉庫地址

event.js模塊

zepto中由許多小的模塊組合合成,基礎(chǔ)的zepto.js模塊,event.js事件處理模塊,ajax.js請求處理模塊等等。其中event.js事件處理模塊的核心完成了zepto中事件綁定on,移除off還有手動觸發(fā)trigger等功能。我們簡單回顧下如何使用zepto的這三大功能。

  • 1
  • 2
let $list = $(".list")

let cb1 = function (e, name) {
  console.log(1, name)
}

let cb2 = function (e, name) {
  console.log(2, name)
}

$list.on("click", cb1)
$list.on("click", cb2)

// 移除事件

// 我們可以指定移除click事件的某個(gè)事件處理程序
$list.off("click", cb1)
// 也可以直接移除click事件
$list.off("click")

// 手動觸發(fā)事件
$list.trigger("click", "qianlongo")

哥們你逗我呢,jQuery,zepto多熟了,誰不會用這個(gè)??!客觀別急,我們今天主要是慢慢來看看它源碼怎么實(shí)現(xiàn)的。

一步步看trigger怎么實(shí)現(xiàn)

直接上代碼

$.fn.trigger = function (event, args) {
  // 對傳入的event進(jìn)行處理,如果是字符串或者純對象,得到一個(gè)自己創(chuàng)建的事件對象
  // 如果傳入的已經(jīng)是個(gè)經(jīng)過$.Event處理的對象,則放入compatible再次改造(其實(shí)就是添加了幾個(gè)方法,和重寫了幾個(gè)方法)
  event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
  // args傳遞給事件處理程序的參數(shù)
  event._args = args
  return this.each(function () {
    // handle focus(), blur() by calling them directly
    if (event.type in focus && typeof this[event.type] == "function") this[event.type]()
    // items in the collection might not be DOM elements
    // 觸發(fā)dom事件
    else if ("dispatchEvent" in this) this.dispatchEvent(event)
    // 因?yàn)閦epto對象內(nèi)部的元素不一定是dom元素,此時(shí)直接觸發(fā)回調(diào)函數(shù)
    else $(this).triggerHandler(event, args)
  })
}

直接貼出trigger函數(shù)的代碼可能我們是懵逼的

$是啥?。。。?/p>

$.fn是啥啊?。。?/p>

$.isPlainObject又是啥啊?。?!

$.Event又是什么鬼?

仿佛有一連串的問題等待著我們解決。

為了直接切入不易理解,我們先來看看zepto中是如何給基礎(chǔ)的zepto.js模塊添加功能的

首先看看zepto.js模塊

var Zepto = (function () {
  // xxxx
  var $ = function (selector, context) {
    return zepto.init(selector, context)
  }
  return $

  zepto.Z.prototype = Z.prototype = $.fn
  // xxxx
})()

window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)

盡量刪除了一些不必要的代碼,可以看到我們平時(shí)使用的Zepto其實(shí)就是其匿名函數(shù)自執(zhí)行內(nèi)部導(dǎo)出的一個(gè)函數(shù)。而$.fn就是其原型

如何給zepto.js模塊增添功能

zepto.js模塊只有一些基礎(chǔ)的功能,比如給dom添加事件的功能就沒有,怎么添加呢?

(function ($) {
  // xxx
  $.fn.on = function () {//xxxx}
  $.fn.off = function () {//xxxx}
  $.fn.trigger = function () {//xxxx}
  $.Event = function () {//xxx}
  // xxx
})(Zepto)

最后縮減掉其他的干擾代碼,可以看到所謂的給zepto.js模塊增添功能,基本上就是在其原型上添加新的方法或者直接在$函數(shù)上定一些靜態(tài)方法。

好啦我們已經(jīng)解決了$,$.fn是啥的疑問了,現(xiàn)在回去開始一步步解讀如何實(shí)現(xiàn)手動觸發(fā)事件。

重新看trigger函數(shù)源碼
$.fn.trigger = function (event, args) {
  // 對傳入的event進(jìn)行處理,如果是字符串或者純對象,得到一個(gè)自己創(chuàng)建的事件對象
  // 如果傳入的已經(jīng)是個(gè)經(jīng)過$.Event處理的對象,則放入compatible再次改造(其實(shí)就是添加了幾個(gè)方法,和重寫了幾個(gè)方法)
  event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
  // args傳遞給事件處理程序的參數(shù)
  event._args = args

  // xxx
}

先把后面的一些代碼給刪除了,我們先理解這幾句代碼。其中非常重要的一個(gè)函數(shù)就是$.Event,至于

isString => 判斷是不是字符串

isPlainObject => 判斷是不是存粹的對象(必須是對象,window對象除外,該對象的原型必須和Object的原型一致)

compatible => 其實(shí)就是對事件對象event做一些擴(kuò)展,比如添加一些方法,重寫一些方法之類的。

這幾個(gè)方法暫時(shí)可以不需要太多關(guān)心.

我們主要看看$.Event,這里面幾乎含有如何手動觸發(fā)一個(gè)dom事件的大部分步驟和內(nèi)容。

我們主要看看$.Event,這里面幾乎含有如何手動觸發(fā)一個(gè)dom事件的大部分步驟和內(nèi)容。

我們主要看看$.Event,這里面幾乎含有如何手動觸發(fā)一個(gè)dom事件的大部分步驟和內(nèi)容。

$.Event是個(gè)啥

創(chuàng)建并初始化一個(gè)指定的dom事件對象, 如果給定了props,則將其擴(kuò)展到事件對象上

 $.Event = function (type, props) {
  // 當(dāng)type是個(gè)對象時(shí),比如{type: "click", data: "qianlongo"}
  if (!isString(type)) props = type, type = props.type
  // click,mousedown,mouseup mousemove對應(yīng)MouseEvent
  // 其他事件對應(yīng)為Events
  // 并把bubbles設(shè)置為true,表示事件冒泡,為false則不冒泡
  var event = document.createEvent(specialEvents[type] || "Events"), bubbles = true
  // 當(dāng)props存在的時(shí)候,對props進(jìn)行循環(huán)處理,將其屬性擴(kuò)展到event對象上
  if (props) for (var name in props) (name == "bubbles") ? (bubbles = !!props[name]) : (event[name] = props[name])
  // 初始化事件對象,第一個(gè)為事件類型,第二個(gè)為冒泡與否,第三個(gè)為是否可以通過preventDefault來阻止瀏覽器默認(rèn)行為
  event.initEvent(type, bubbles, true)
  // 再對創(chuàng)造出來的時(shí)間對象處理一番并返回
  return compatible(event)
}

注釋已經(jīng)寫的很清楚了,這個(gè)函數(shù)就是返回一個(gè)經(jīng)過初始化了的事件對象

到這里我們直接歸納一下要手動觸發(fā)一個(gè)dom事件的基本步驟

手動觸發(fā)一個(gè)dom事件,需要3步,如果你對document.createEvent,不是很熟悉,可以點(diǎn)擊查看。

創(chuàng)建一個(gè)事件對象 document.createEvent(event)

初始化事件對象 event.initEvent(type, bubbles, true)

分發(fā)事件 dom.dispatchEvent(event)

到這里已經(jīng)完成了前面兩步,還剩最后一步了,在來看trigger剩下的代碼

手動觸發(fā)dom事件最后一步
 $.fn.trigger = function (event, args) {
  // 對傳入的event進(jìn)行處理,如果是字符串或者純對象,得到一個(gè)自己創(chuàng)建的事件對象
  // 如果傳入的已經(jīng)是個(gè)經(jīng)過$.Event處理的對象,則放入compatible再次改造(其實(shí)就是添加了幾個(gè)方法,和重寫了幾個(gè)方法)
  event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
  // args傳遞給事件處理程序的參數(shù)
  event._args = args
  return this.each(function () {
    // handle focus(), blur() by calling them directly
    if (event.type in focus && typeof this[event.type] == "function") this[event.type]()
    // items in the collection might not be DOM elements
    // 觸發(fā)dom事件
    else if ("dispatchEvent" in this) this.dispatchEvent(event)
    // 因?yàn)閦epto對象內(nèi)部的元素不一定是dom元素,此時(shí)直接觸發(fā)回調(diào)函數(shù)
    else $(this).triggerHandler(event, args)
  })
}

最后一步其實(shí)就是將當(dāng)前選中的元素進(jìn)行一次each遍歷,然后判斷要觸發(fā)的事件是不是focus或者blur,如果是就直接執(zhí)行。

再進(jìn)一步,如果dispatchEvent方法在當(dāng)前的dom元素屬性中存在,那么便將該事件觸發(fā)。(為什么要這一步呢?因?yàn)槲覀冎?()函數(shù)的使用方式有很多,有些方式得到的zepto對象是沒有選中dom節(jié)點(diǎn)的)

最后還有一個(gè)else分支,這個(gè)分支處理走的不是手動觸發(fā)事件,而是直接觸發(fā)注冊事件時(shí)添加的事件處理程序(因?yàn)檫@里涉及到zepto事件模塊中如何管理元素與事件隊(duì)列的映射關(guān)系,篇幅會比較長,會在接下來的文章中說,這里不展開說明)

手動diy一個(gè)

根據(jù)上面的描述,手動觸發(fā)DOM事件,原來并沒有那么神奇,完成三步,即可達(dá)到目標(biāo)。我們自己來手動寫一個(gè)示例

  • 1
  • 2
  • 3
let $list = document.querySelector(".list")
let $item1 = document.querySelector(".item1")

$list.addEventListener("click", function () {
  console.log(this.innerHTML)
}, false)

$item1.addEventListener("click", function () {
  console.log(this.innerHTML)
}, false)

// 1. 創(chuàng)建一個(gè)事件對象 document.createEvent(event)
let event = document.createEvent("Event")
// 2. 初始化事件對象 event.initEvent(type, bubbles, true)
event.initEvent("click", true, true)
// 3. 分發(fā)事件  dom.dispatchEvent(event)
$item1.dispatchEvent(event)

這個(gè)時(shí)候控制臺打印出了

1

  • 1
  • 2
  • 3
  • 1是item1的事件處理函數(shù)打印出來的。

    后面的li那部分則是list打印出來的。

    如果將initEvent的第二個(gè)參數(shù)設(shè)置為false,將不允許冒泡,則只會打印出1

    結(jié)尾

    如果這部分對你有點(diǎn)點(diǎn)幫助,點(diǎn)個(gè)star好不好呀! ???

    倉庫地址

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

    轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/50849.html

    相關(guān)文章

    • zepto.js學(xué)習(xí)如何手動(trigger)觸發(fā)DOM事件

      摘要:好啦我們已經(jīng)解決了是啥的疑問了,現(xiàn)在回去開始一步步解讀如何實(shí)現(xiàn)手動觸發(fā)事件。我們主要看看這里面幾乎含有如何手動觸發(fā)一個(gè)事件的大部分步驟和內(nèi)容。 前言 前端在最近幾年實(shí)在火爆異常,vue、react、angular各路框架層出不窮,咱們要是不知道個(gè)雙向數(shù)據(jù)綁定,不曉得啥是虛擬DOM,也許就被鄙視了?;馃岬谋澈笸彩菬o盡的浮躁,學(xué)習(xí)這些先進(jìn)流行的類庫或者框架可以讓我們走的更快,但是靜下心...

      spacewander 評論0 收藏0
    • zepto.js學(xué)習(xí)如何手動(trigger)觸發(fā)DOM事件

      摘要:好啦我們已經(jīng)解決了是啥的疑問了,現(xiàn)在回去開始一步步解讀如何實(shí)現(xiàn)手動觸發(fā)事件。我們主要看看這里面幾乎含有如何手動觸發(fā)一個(gè)事件的大部分步驟和內(nèi)容。 前言 前端在最近幾年實(shí)在火爆異常,vue、react、angular各路框架層出不窮,咱們要是不知道個(gè)雙向數(shù)據(jù)綁定,不曉得啥是虛擬DOM,也許就被鄙視了?;馃岬谋澈笸彩菬o盡的浮躁,學(xué)習(xí)這些先進(jìn)流行的類庫或者框架可以讓我們走的更快,但是靜下心...

      fuyi501 評論0 收藏0
    • 如何實(shí)現(xiàn)swipe、tap、longTap等自定義事件

      摘要:分別存儲事件的定時(shí)器。事件定時(shí)器延時(shí)時(shí)間存儲事件對象滑動方向判斷我們根據(jù)下圖以及對應(yīng)的代碼來理解滑動的時(shí)候方向是如何判定的。取消長按,以及取消所有事件取消長按取消所有事件方式都是類似,先調(diào)用取消定時(shí)器,然后釋放對應(yīng)的變量,等候垃圾回收。 前言 移動端原生支持touchstart、touchmove、touchend等事件,但是在平常業(yè)務(wù)中我們經(jīng)常需要使用swipe、tap、double...

      羅志環(huán) 評論0 收藏0
    • Zepto源碼之Event模塊

      摘要:不支持事件冒泡帶來的直接后果是不能進(jìn)行事件委托,所以需要對和事件進(jìn)行模擬。調(diào)用函數(shù),分隔出參數(shù)的事件名和命名空間。這里判斷是否為函數(shù),即第一種傳參方式,調(diào)用函數(shù)的方法,將上下文對象作為的第一個(gè)參數(shù),如果存在,則與的參數(shù)合并。 Event 模塊是 Zepto 必備的模塊之一,由于對 Event Api 不太熟,Event 對象也比較復(fù)雜,所以乍一看 Event 模塊的源碼,有點(diǎn)懵,細(xì)看下...

      vpants 評論0 收藏0

    發(fā)表評論

    0條評論

    最新活動
    閱讀需要支付1元查看
    <