向zepto.js进修怎样手动(trigger)触发DOM事宜

媒介

前端在近来几年着实火爆非常,vue、react、angular各路框架屡见不鲜,我们假如不晓得个双向数据绑定,不晓得啥是假造DOM,或许就被蔑视了。炽热的背地每每也是无尽的急躁,进修这些先进盛行的类库或许框架能够让我们走的更快,然则静下心来回归基础,把基石打稳固,却能够让我们走的更稳,更远。

近来一向在看zepto的源码,愿望经由过程进修它控制一些框架设想的技能,也将良久不再拾起的js基础从新复习稳固一遍。假如你对这个系列感兴趣,迎接点击下方地点watch,随时关注动态。这篇文章重要想说一下zepto中事宜模块(event.js)的trigger完成道理。

原文地点

堆栈地点

《向zepto.js进修怎样手动(trigger)触发DOM事宜》

<!–more–>

event.js模块

zepto中由许多小的模块组合合成,基础的zepto.js模块,event.js事宜处置惩罚模块,ajax.js要求处置惩罚模块等等。个中event.js事宜处置惩罚模块的中心完成了zepto中事宜绑定on,移除off另有手动触发trigger等功用。我们简朴回忆下怎样运用zepto的这三大功用。


<ul class="list">
  <li>1</li>
  <li>2</li>
</ul>
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事宜的某个事宜处置惩罚顺序
$list.off('click', cb1)
// 也能够直接移除click事宜
$list.off('click')

// 手动触发事宜
$list.trigger('click', 'qianlongo')

《向zepto.js进修怎样手动(trigger)触发DOM事宜》

哥们你逗我呢,jQuery,zepto多熟了,谁不会用这个啊!客观别急,我们本日主假如慢慢来看看它源码怎样完成的。

一步步看trigger怎样完成

直接上代码

$.fn.trigger = function (event, args) {
  // 对传入的event举行处置惩罚,假如是字符串或许纯对象,获得一个本身建立的事宜对象
  // 假如传入的已是个经由$.Event处置惩罚的对象,则放入compatible再次革新(实在就是增加了几个要领,和重写了几个要领)
  event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
  // args传递给事宜处置惩罚顺序的参数
  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
    // 触发dom事宜
    else if ('dispatchEvent' in this) this.dispatchEvent(event)
    // 由于zepto对象内部的元素不一定是dom元素,此时直接触发还调函数
    else $(this).triggerHandler(event, args)
  })
}

直接贴出trigger函数的代码能够我们是懵逼的

$是啥啊!!!

$.fn是啥啊!!!

$.isPlainObject又是啥啊!!!

$.Event又是什么鬼?

似乎有一连串的题目等待着我们处理。

为了直接切入不容易明白,我们先来看看zepto中是怎样给基础的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)

只管删除了一些不必要的代码,能够看到我们日常平凡运用的Zepto实在就是其匿名函数自实行内部导出的一个函数。而$.fn就是其原型

怎样给zepto.js模块增加功用

zepto.js模块只要一些基础的功用,比方给dom增加事宜的功用就没有,怎样增加呢?


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

末了缩减掉其他的滋扰代码,能够看到所谓的给zepto.js模块增加功用,基础上就是在其原型上增加新的要领或许直接在$函数上定一些静态要领。

好啦我们已处理了$,$.fn是啥的疑问了,如今归去最先一步步解读怎样完成手动触发事宜。

从新看trigger函数源码

$.fn.trigger = function (event, args) {
  // 对传入的event举行处置惩罚,假如是字符串或许纯对象,获得一个本身建立的事宜对象
  // 假如传入的已是个经由$.Event处置惩罚的对象,则放入compatible再次革新(实在就是增加了几个要领,和重写了几个要领)
  event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
  // args传递给事宜处置惩罚顺序的参数
  event._args = args

  // xxx
}

先把背面的一些代码给删除了,我们先明白这几句代码。个中非常重要的一个函数就是$.Event,至于

isString => 推断是不是是字符串

isPlainObject => 推断是不是是存粹的对象(必需是对象,window对象除外,该对象的原型必需和Object的原型一致)

compatible => 实在就是对事宜对象event做一些扩大,比方增加一些要领,重写一些要领之类的。

这几个要领临时能够不须要太多体贴.

我们重要看看$.Event,这内里险些含有怎样手动触发一个dom事宜的大部分步骤和内容。

我们重要看看$.Event,这内里险些含有怎样手动触发一个dom事宜的大部分步骤和内容。

我们重要看看$.Event,这内里险些含有怎样手动触发一个dom事宜的大部分步骤和内容。

$.Event是个啥

建立并初始化一个指定的dom事宜对象, 假如给定了props,则将其扩大到事宜对象上

 $.Event = function (type, props) {
  // 当type是个对象时,比方{type: 'click', data: 'qianlongo'}
  if (!isString(type)) props = type, type = props.type
  // click,mousedown,mouseup mousemove对应MouseEvent
  // 其他事宜对应为Events
  // 并把bubbles设置为true,示意事宜冒泡,为false则不冒泡
  var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
  // 当props存在的时刻,对props举行轮回处置惩罚,将其属性扩大到event对象上
  if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
  // 初始化事宜对象,第一个为事宜范例,第二个为冒泡与否,第三个为是不是能够经由过程preventDefault来阻挠浏览器默许行动
  event.initEvent(type, bubbles, true)
  // 再对制造出来的时候对象处置惩罚一番并返回
  return compatible(event)
}

解释已写的很清晰了,这个函数就是返回一个经由初始化了的事宜对象

到这里我们直接归结一下要手动触发一个dom事宜的基础步骤

手动触发一个dom事宜,须要3步,假如你对document.createEvent,不是很熟悉,能够点击检察。

  1. 建立一个事宜对象 document.createEvent(event)

  2. 初始化事宜对象 event.initEvent(type, bubbles, true)

  3. 分发事宜 dom.dispatchEvent(event)

到这里已完成了前面两步,还剩末了一步了,在来看trigger剩下的代码

手动触发dom事宜末了一步

 $.fn.trigger = function (event, args) {
  // 对传入的event举行处置惩罚,假如是字符串或许纯对象,获得一个本身建立的事宜对象
  // 假如传入的已是个经由$.Event处置惩罚的对象,则放入compatible再次革新(实在就是增加了几个要领,和重写了几个要领)
  event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
  // args传递给事宜处置惩罚顺序的参数
  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
    // 触发dom事宜
    else if ('dispatchEvent' in this) this.dispatchEvent(event)
    // 由于zepto对象内部的元素不一定是dom元素,此时直接触发还调函数
    else $(this).triggerHandler(event, args)
  })
}

末了一步实在就是将当前选中的元素举行一次each遍历,然后推断要触发的事宜是不是是focus或许blur,假如是就直接实行。

再进一步,假如dispatchEvent要领在当前的dom元素属性中存在,那末便将该事宜触发。(为何要这一步呢?由于我们晓得$()函数的运用体式格局有许多,有些体式格局获得的zepto对象是没有选中dom节点的)

末了另有一个else分支,这个分支处置惩罚走的不是手动触发事宜,而是直接触发注册事宜时增加的事宜处置惩罚顺序(由于这里涉及到zepto事宜模块中怎样治理元素与事宜队列的映照关联,篇幅会比较长,会在接下来的文章中说,这里不睁开申明)

手动diy一个

依据上面的形貌,手动触发DOM事宜,本来并没有那末奇异,完成三步,即可到达目的。我们本身来手动写一个示例


<ul class="list">
  <li class="item1">1</li>
  <li>2</li>
  <li>3</li>
</ul>

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. 建立一个事宜对象 document.createEvent(event)
let event = document.createEvent('Event')
// 2. 初始化事宜对象 event.initEvent(type, bubbles, true)
event.initEvent('click', true, true)
// 3. 分发事宜  dom.dispatchEvent(event)
$item1.dispatchEvent(event)

这个时刻控制台打印出了

1

<li class="item1">1</li>
<li>2</li>
<li>3</li>

1是item1的事宜处置惩罚函数打印出来的。

背面的li那部分则是list打印出来的。

假如将initEvent的第二个参数设置为false,将不许可冒泡,则只会打印出1

末端

假如这部分对你有点点协助,点个star好不好呀! ???

堆栈地点

    原文作者:谦龙
    原文地址: https://segmentfault.com/a/1190000009683219
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞