某个博客说,上半年单身已经结束,下半年单身还将继续,莫名喜感
去年恬不知耻的去看了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元素上触发事件。
重点语法:
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');
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