這篇文章主要為大家詳細(xì)介紹了Jquery實(shí)現(xiàn)ready和bind事件的相關(guān)資料,感興趣的小伙伴們可以參考一下
講這一節(jié)之前,先回顧之前一段代碼:
(function (win) {
var _$ = function (selector, context) {
return new _$.prototype.Init(selector, context);
}
_$.prototype = {
Init: function (selector, context) {
this.elements = [];
var context = context || document;
if (context.querySelectorAll) {
var arr = context.querySelectorAll(selector);
for (var i = 0; i < arr.length; i++) {
this.elements.push(arr[i]);
}
}
////這一塊是選擇器的實(shí)現(xiàn),沒有寫完,可以自己實(shí)現(xiàn)
},
each: function (callback) {
if (this.elements.length > 0) {
for (var i = 0; i < this.elements.length; i++) {
callback.call(this, i, this.elements[i]);
}
}
}
}
_$.prototype.Init.prototype = _$.prototype;
window.$ = _$;
})(window || global);
上面我們實(shí)現(xiàn)了節(jié)點(diǎn)的查找,今天要講的是對節(jié)點(diǎn)的事件綁定。
熟悉Jquery 源碼的TX應(yīng)該知道:我們上面的代碼少了ready事件,只是針對節(jié)點(diǎn)進(jìn)行查詢,并沒有將document對象考慮進(jìn)去。我之前單獨(dú)講過window.onload和 document. ready的區(qū)別,還對document.ready事件進(jìn)行了擴(kuò)展。
現(xiàn)在我們把擴(kuò)展方法加到這里面:
我們的Init方法要改正一下:
Init: function (selector, context) {
this.elements = [];
if (typeof selector === "function") {
this.elements.push(document);
this.ready(selector);
}
else {
var context = context || document;
var isDocument = function (ele) {
var tostring = Object.prototype.toString;
return tostring.call(ele) == "[object HTMLDocument]" || "[object Document]";
}
if (isDocument(selector)) {
this.elements.push(selector);
}
else if (context.querySelectorAll) {
var arr = context.querySelectorAll(selector);
for (var i = 0; i < arr.length; i++) {
this.elements.push(arr[i]);
}
}
}
}
這段代碼的大致意思是:如果傳入的參數(shù)selector是function類型,就執(zhí)行ready事件。如果是document就將document對象插入到this.elements數(shù)組里面(這個(gè)傳入之后,會在ready事件里面進(jìn)行判斷)。如果是字符竄,就查詢出節(jié)點(diǎn),循環(huán)插入到this.elements數(shù)組里面,沒什么難度。主要考慮到$(document).ready和$(function(){})這兩種ready事件的寫法。
我們接下來把ready函數(shù)加進(jìn)來:
ready: function (callback) {
var isDocument = function (ele) {
var tostring = Object.prototype.toString;
return tostring.call(ele) == "[object HTMLDocument]" | "[object Document]";
}
if (isDocument(this.elements[0])) {
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', function () {
document.removeEventListener('DOMContentLoaded', arguments.callee, false);
callback();
}, false);
}
else if (document.attachEvent) {
document.attachEvent('onreadystatechange', function () {
if (document.readyState == "complete") {
document.detachEvent('onreadystatechange', arguments.callee);
callback();
}
});
}
else if (document.lastChild == document.body) {
callback();
}
}
}
這段代碼我之前其實(shí)講過了(onload和ready的區(qū)別),不知道的可以看看。
現(xiàn)在ready事件,我們實(shí)現(xiàn)了。然后就可以針對節(jié)點(diǎn)進(jìn)行事件注冊了。
我們來實(shí)現(xiàn)bind函數(shù),代碼如下:
bind: function (type, callback) {
if (document.addEventListener) {
this.each(function (i, item) {
item.addEventListener(type, callback, false);
});
}
else if (document.attachEvent) {
this.each(function (i, item) {
item.attachEvent('on' + type, callback);
});
}
else {
this.each(function (i, item) {
tem['on' + type] = callback;
});
}
}
這里面都是些兼容性代碼,實(shí)現(xiàn)節(jié)點(diǎn)的事件注冊。之前的each,大家可能不知道是要干嘛的?,F(xiàn)在在這里面就用到了。
主要作用是針對節(jié)點(diǎn)循環(huán)做一些操作。
完整代碼,來一份:
(function (win) {
var _$ = function (selector, context) {
return new _$.prototype.Init(selector, context);
}
_$.prototype = {
Init: function (selector, context) {
this.elements = [];
if (typeof selector === "function") {
this.elements.push(document);
this.ready(selector);
}
else {
var context = context || document;
var isDocument = function (ele) {
var tostring = Object.prototype.toString;
return tostring.call(ele) == "[object HTMLDocument]" | "[object Document]";
}
if (isDocument(selector)) {
this.elements.push(selector);
}
else if (context.querySelectorAll) {
var arr = context.querySelectorAll(selector);
for (var i = 0; i < arr.length; i++) {
this.elements.push(arr[i]);
}
}
}
},
each: function (callback) {
var length = this.elements.length;
if (length > 0) {
for (var i = 0; i < length; i++) {
callback.call(this, i, this.elements[i]);
}
}
},
ready: function (callback) {
var isDocument = function (ele) {
var tostring = Object.prototype.toString;
return tostring.call(ele) == "[object HTMLDocument]" | "[object Document]";
}
if (isDocument(this.elements[0])) {
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', function () {
document.removeEventListener('DOMContentLoaded', arguments.callee, false);
callback();
}, false);
}
else if (document.attachEvent) {
document.attachEvent('onreadystatechange', function () {
if (document.readyState == "complete") {
document.detachEvent('onreadystatechange', arguments.callee);
callback();
}
});
}
else if (document.lastChild == document.body) {
callback();
}
}
},
bind: function (type, callback) {
if (document.addEventListener) {
this.each(function (i, item) {
item.addEventListener(type, callback, false);
});
}
else if (document.attachEvent) {
this.each(function (i, item) {
item.attachEvent('on' + type, callback);
});
}
else {
this.each(function (i, item) {
tem['on' + type] = callback;
});
}
}
}
_$.prototype.Init.prototype = _$.prototype;
window.$ = _$;
})(window);
這幾個(gè)函數(shù)基本上可以實(shí)現(xiàn)對節(jié)點(diǎn)的事件注冊了。其余的一些特效,還需要擴(kuò)展。如果感興趣的話可以自己在 _$.prototype對象里面加方法。
以上就是本文的全部內(nèi)容,希望能夠幫助大家。