まず、Element の DOM 拡張に関する技術的なアイデアについて話しましょう。私も 1 日かけてコードを読み、いくつかの洞察を得ることができました。
プロトタイプを使用する場合、最も一般的に使用されるコードは $('div1') です。展開された要素オブジェクトを取得するには、次のようなさまざまな拡張メソッドを使用できます。
$('div1').addClassName('loading').show();
したがって、これを次のように使用する必要があります。 Element の拡張を検討するためのエントリ ポイント。
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = argument.length; i elements.push($(arguments[i]));
要素を返す;
if (Object.isString(element))
element = document.getElementById(element); >return Element.extend(element);
}
この関数は 1 回の賢い再帰で複数のパラメータを処理できることに本当に感銘を受けました。コードのキーは次のとおりです: Element.extend(element) 拡張する前は、要素は単なる通常の DOM オブジェクトです。拡張後は、シークレットが拡張されていることがわかります。
Element.extend(element) なので、当然、extend だけを勉強することはできません。まず Element とは何かを理解する必要があります。
(function() {
var 要素 = this.Element;
this.Element = function(tagName, 属性) {
属性 = 属性 || { };
タグ名 = タグ名。 toLowerCase();
var キャッシュ = Element.cache;
if (Prototype.Browser.IE && 属性.name) {
タグ名 = '
'; 🎜> return Element.writeAttribute(document.createElement(tagName), 属性);
} if (!cache[tagName]) queue[tagName] = Element.extend(document.createElement(tagName)); 🎜> Return Element.writeAttribute(cache[tagName].cloneNode(false), 属性);
}
Object.extend(this.Element, element || { }); (window);
この種のコードは、よりパーソナライズされたものになっており、基本的な構造は次のとおりです: (function(){...}).call(window);省略記号の部分でウィンドウを指します。
var element=this.Element; この行を理解するのは難しくありませんが、重要な点は this.Element がまだ定義されていないことです。次のステップでは、クラス window.Element クラスを定義します。このクラスには、tagName、attribute の 2 つのパラメータがあります。その機能は、要素を作成し、指定された純粋なタグに対応する DOM オブジェクトをキャッシュに入れることです。要素の作成後、指定された属性値が書き込まれます。ここで注意してください:
writeAttribute と readAttribute の 2 つの関数には属性の読み取りと書き込みの機能があることは明らかですが、そのコードは主に、異なるブラウザーでの属性の読み取りと書き込みに起因します。違う。
これは Element クラスのコンストラクターの定義で、その後に Element.cache = { }; キャッシュの種類を説明するのは簡単ではありませんが、さまざまなタグの DOM 要素オブジェクトの純粋なバージョンのキャッシュです。 ?こんなことを言うのはとても嫌なことだ。直後に Element.Methods={......} があり、ここでほぼすべての拡張メソッドが定義されています。ここでの拡張メソッドにはすべて 1 つの機能があり、コード内でこれを使用するものはありません。すべて要素参照をそのまま渡します。このように定義されたのには理由があります。後で教えます。
Element について簡単に説明しましたが、次は Element.extend について話さなければなりません。
Element.extend = (function() {
if (Prototype.BrowserFeature.SpecificElementExtensions)
return Prototype.K;
var Methods = { }, ByTag = Element.Methods.ByTag;
var extend = Object.extend(function(element) {
if (!element || element._extendedByPrototype ||
element.nodeType != 1 || element == window) return element;
var Methods = Object.clone(Methods),
tagName = element.tagName, property, value;
// 特定のタグのメソッドを拡張
if (ByTag[tagName]) Object.extend(methods, ByTag[ tagName]);
for (メソッド内のプロパティ) {
value = メソッド[プロパティ];
if (Object.isFunction(value) && !(要素内のプロパティ))
要素[プロパティ] = value.methodize();
element._extendedByPrototype = Prototype.emptyFunction;
return element;
refresh: function() {
//すべてのタグ (Safari にはこれは必要ありません)
if (!Prototype.BrowserFeature.ElementExtensions) {
Object.extend(Methods, Element.Methods);
Object.extend(Methods, Element.Methods.Simulated);
}
}
});
extend.refresh();
return extend;
})();
第一行の原理我不大肯定,不说,下面的代推看似复杂,待我抽出它的大概構造来:
var extend=Object.extend(function(element){……} ,{リフレッシュ:関数(){……}});
拡張内で、最初の関数は、XXXX.Methods からメソッドを取得し、要素に組み込むという考えに基づいています。メソッド取得メソッド
2、要素が表内の入力可能な要素である場合、Form.Element から取得メソッド
3、すべての要素が Element.Methods から取得されます。
つまり、これはさまざまな状況を考慮する必要があり、本来は if を組み合わせるべきものですが、これにより Element.Methods.ByTag が巧みに設計されています。そのため、この問題は解決されています。 Object.isFunction(value) && !(要素内のプロパティ))
element[プロパティ] = value.methodize();
メソッド内の要素が関数でない場合、または要素内に関数が存在する場合、この問題は解決され、value.methodize() は、前のオフが適用され、methodize の機能が現在適用されます。その使用方法は通常次のとおりです。
obj.methodname=functionname.methodize();
このように、使用時には、obj オブジェクトが最初のパラメータとしてこの関数の名前を入力します。元素のtagName来获得应当从哪个Methods获得扩展,那么,我们必知一下ByTag的详情,查找一下,找到了:
Object.extend(Element.Methods.ByTag, {
"FORM": Object.clone(Form.Methods)、
"INPUT": Object.clone(Form.Element.Methods)、
"SELECT": Object.clone(Form.Element.Methods)、
"TEXTAREA ": Object.clone(Form.Element.Methods)
});
わかりました、差はありません。これで完了です。