このセクションについて説明する前に、前のコード部分を確認してみましょう:
(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 イベントがなく、ドキュメント オブジェクトを考慮せずにノードのみをクエリしていることを知っておく必要があります。以前に 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]); } } } }
このコードの一般的な意味は次のとおりです。渡されたパラメーター セレクターが関数タイプの場合、ready イベントを実行します。ドキュメントの場合は、this.elements配列にドキュメントオブジェクトを挿入します(これを渡した後、readyイベントで判定されます)。文字シフトの場合は、ノードをクエリしてループ内の this.elements 配列に挿入するだけです。これは難しくありません。主に、$(document).ready と $(function(){}) という 2 つの 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 の違い)。知らない場合は、見てください。
これで、準備完了のイベントが実装されました。その後、ノードのイベントを登録できます。
バインド関数を実装しましょう。コードは次のとおりです:
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; }); } }
ノード イベント登録を実装するための互換性コードをいくつか示します。それぞれの前に、それが何のためにあるのかわからないかもしれません。今ここで使われているんですね。
主な機能は、ノード ループでいくつかの操作を実行することです。
完全なコードはここに来てください:
(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 オブジェクトにメソッドを追加できます。
以上がこの記事の全内容です。皆様のお役に立てれば幸いです。