仿Zepto自动触发事件函数---trigger()

某个博客说,上半年单身已经结束,下半年单身还将继续,莫名喜感

去年恬不知耻的去看了jQuery源码,被虐之后接着去看zepto源码,现实给了我很好教训。看不懂,枯燥,味同嚼蜡。要不是知道自己年纪经不起荒废,要不是知道很多高手成神之路都少不了去看看源码,早就坚持不下去。

话说,如果当初读书时候有现在一半的坚持,或许也不至于混的这么差,可惜没有如果,只有更加的努力。

10月份项目修改用到了事件自动触发,所以就来学学内部实现原理。

trigger
trigger(event, [args])   ⇒ self
在对象集合的元素上触发指定的事件。事件可以是一个字符串类型,也可以是一个 通过$.Event 定义的事件对象。如果给定args参数,它会作为参数传递给事件函数。

// add a handler for a custom event
$(document).on('mylib:change', function(e, from, to){
  console.log('change on %o with data %s, %s', e.target, from, to)
})
// trigger the custom event
$(document.body).trigger('mylib:change', ['one', 'two'])
 Zepto仅仅支持在dom元素上触发事件。

上面是trigger的使用方法,相信大家都很熟悉,自动触发某个事件,多发生在,进入某个页面,弹窗,要进行一些重复的事件操作。

重点语法:

addEventListener

createEvent

initEvent

dispatchEvent

简单说下步骤,监听事件,创建事件,初始化事件,触发事件。什么意思呢?具体点就是我们原来有个事件,然后我们要使用js触发它,那么我们就必须创建触发事件,为何要这样?因为事件也分类型,不同类型初始化方式不一样,请看下表

createEvent()方法返回新创建的Event对象,支持一个参数,表示事件类型,具体见下表:

参数	        事件接口	初始化方法
HTMLEvents	HTMLEvent	initEvent()
MouseEvents	MouseEvent	initMouseEvent()
UIEvents	UIEvent	        initUIEvent()
有三种参数,有三种不一样的初始化方法,当然常用就是initEvent,详细的我也不懂了,百度吧。如果不考虑兼容或者只是面的移动端,就是这么简单了。

//仿zepto事件自动出发函数

let trigger = (dom,event) => {
    //创建Event事件
    let creatEvent = document.createEvent('Event');
    //初始化Event事件,注意区分三种类型,后面两个true是指是否支持冒泡,是否可以撤销,默认单击才触发
    creatEvent.initEvent(event,true,true);
    //自动触发(分发事件) dom.dispatchEvent
    dom.dispatchEvent(creatEvent);
}


//获取dom
let input = document.querySelector('input');
//监听点击事件
input.addEventListener('click',() => {
    console.log('监听点击事件');
});
//自动触发
trigger(input,'click');

上面例子在加载页面完成时候就会触发input的click事件,如果点击按钮,也会触发click。但是直接使用click并不是一件好事情,为避免引起不必要的bug,我们也可以自定义事件。

addEventListener('click-test1'fn)
根据上面方法,我们改造下

//仿zepto事件自动出发函数

let trigger = (dom,event) => {
    //创建Event事件
    let creatEvent = document.createEvent('Event');
    //初始化Event事件,注意区分三种类型,后面两个true是指是否支持冒泡,是否可以撤销,默认单击才触发
    creatEvent.initEvent(event,true,true);
    //自动触发(分发事件) dom.dispatchEvent
    dom.dispatchEvent(creatEvent);
}


//获取dom
let input = document.querySelector('input');
//监听点击事件
input.addEventListener('click',() => {
    console.log('监听点击事件');
});
//监听点击test1事件
input.addEventListener('click-test1',() => {
    console.log('监听点击事件1');
});
input.addEventListener('click-test2',() => {
    console.log('监听点击事件2');
});
input.addEventListener('click-test3',() => {
    console.log('监听点击事件3');
});
//监听鼠标经过事件
input.addEventListener('mouseover',() => {
    console.log('监听鼠标经过事件');
});
//监听鼠标经过test1事件
input.addEventListener('mouseover-test1',() => {
    console.log('监听鼠标经过事件1');
});
//自动触发
trigger(input,'click-test1');
trigger(input,'click-test2');
trigger(input,'click-test3');

trigger(input,'mouseover');
trigger(input,'mouseover-test1');

到了这里,基本上已经实现了zepto的自动触发事件函数,剩下来就是模拟zepto,链式调用。

仿造zepto结构,应该说是直接抄袭,原理:

1.构造一个{} Zepto对象,返回zepto.init()函数

2.在zepto.init构造一个dom数组,修改浏览器api的_proto_指针,让它指向$.fn,dom返回了querySelectorAll操作,不过这里不做字符串处理

3.$.fn为静态方法(dom方法),这里只提供trigger方法

4.zepto.Z.prototype = Z.prototype = $.fn        $.zepto = zepto         return $   这三个分别是原型链串联,返回$  这样每次运行Zepto插件就会注册一个全局变量$,所以就能够使用$(xxx)

var Zepto = (function() {
    var $,zepto = {};
    
    zepto.init = function (selector, context) {
        var dom = [];
        //这个__proto__是系统级变量,我觉得zepto不该重置 ,但是不重置的话实例便找不到方法了!!!
        dom.__proto__ = $.fn
        dom.selector = selector;
        //dom操作,这里直接就是querySelectorAll
        dom = zepto.qsa(document, selector);
        return zepto.Z(dom, selector)// 可以看这里,无论以上过程经历了什么,都要经过此函数,目的是将数组转化为类数组对象。;
    };
    zepto.Z = function(dom, selector) {
        return new Z(dom, selector)
    }
    /**
     * 一个构造函数,将dom对象中的属性和方法都复制到this下,并添加了两个属性,length和selector,这个函数的目的是将DOM对象转化为供zepto使用的类数组对象
     */
    function Z(dom, selector) {
        var i, len = dom ? dom.length : 0
        for (i = 0; i < len; i++) this[i] = dom[i]
        this.length = len
        this.selector = selector || ''
    }
    zepto.qsa = function(element, selector){
        return element.querySelectorAll(selector);
    }
    $ = function (selector, context) {
        return zepto.init(selector, context);
    };
    $.fn = {
        trigger: function(event){
            //创建Event事件
            let creatEvent = document.createEvent('Event');
            //初始化Event事件,注意区分三种类型,后面两个true是指是否支持冒泡,是否可以撤销,默认单击才触发
            creatEvent.initEvent(event,true,true);
            //自动触发(分发事件) dom.dispatchEvent
            this[0].dispatchEvent(creatEvent);
        }
        // 省略
    }
    zepto.Z.prototype = Z.prototype = $.fn
    $.zepto = zepto
    return $
})();


 
  

调用实现自动触发事件

console.log(Zepto('input'))
  
  window.Zepto = Zepto
  window.$ === undefined && (window.$ = Zepto)

//获取dom
let input = document.querySelector('input');
//监听点击事件
input.addEventListener('click',() => {
    console.log('监听点击事件');
});
//监听点击test1事件
input.addEventListener('click-test1',() => {
    console.log('监听点击事件1');
});
input.addEventListener('click-test2',() => {
    console.log('监听点击事件2');
});
input.addEventListener('click-test3',() => {
    console.log('监听点击事件3');
});
//监听鼠标经过事件
input.addEventListener('mouseover',() => {
    console.log('监听鼠标经过事件');
});
//监听鼠标经过test1事件
input.addEventListener('mouseover-test1',() => {
    console.log('监听鼠标经过事件1');
});
//自动触发
$('input').trigger('click');

到这里就简单的实现了trigger自动触发事件,当然也简单的抄袭Zepto基本实现原理,为了明天会更好,坚持学习。


参考网址: http://www.jianshu.com/p/07ef7745668b

http://www.bubuko.com/infodetail-1131119.html

https://segmentfault.com/a/1190000007515865?_ea=1389405

http://www.cnblogs.com/yexiaochai/p/3868133.html

你可能感兴趣的:(zepto学习和源码分析系列)