讲这一节之前,先回顾之前一段代码:
(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]);}}////这一块是选择器的实现,没有写完,可以自己实现},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);上面我们实现了节点的查找,今天要讲的是对节点的事件绑定。
熟悉Jquery 源码的TX应该知道:我们上面的代码少了ready事件,只是针对节点进行查询,并没有将document对象考虑进去。我之前单独讲过window.onload和 document. ready的区别,还对document.ready事件进行了扩展。
现在我们把扩展方法加到这里面:
我们的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]);}}}}这段代码的大致意思是:如果传入的参数selector是function类型,就执行ready事件。如果是document就将document对象插入到this.elements数组里面(这个传入之后,会在ready事件里面进行判断)。如果是字符窜,就查询出节点,循环插入到this.elements数组里面,没什么难度。主要考虑到$(document).ready和$(function(){})这两种ready事件的写法。
我们接下来把ready函数加进来:
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();}}}这段代码我之前其实讲过了(onload和ready的区别),不知道的可以看看。
现在ready事件,我们实现了。然后就可以针对节点进行事件注册了。
我们来实现bind函数,代码如下:
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;});}}这里面都是些兼容性代码,实现节点的事件注册。之前的each,大家可能不知道是要干嘛的。现在在这里面就用到了。
主要作用是针对节点循环做一些操作。
完整代码,来一份:
(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);这几个函数基本上可以实现对节点的事件注册了。其余的一些特效,还需要扩展。如果感兴趣的话可以自己在 _$.prototype对象里面加方法。
以上就是本文的全部内容,希望能够帮助大家。