2

初期化を簡単にするために、ライブラリを jQuery プラグインに変換しています。アイデアは、プラグインが実行される要素のタイプに応じて異なる動作をするということです。

要素が a の場合、<p>正しく初期化します。ただし、要素が別のブロック要素である場合は、先頭に a<p>を追加します。要素がインライン要素である場合は、リストから削除する必要があります。これは問題なく機能しており、データは適切な要素 ( ) にアタッチされています<p><p>連鎖能力については、毎回、を返したいと思います。

から始めると$('p').Plugin({...data...})、確かに<p>. ただし、チェーンを で開始すると$('div).Plugin({...data...})<div>代わりに が返されます。プラグインは特定の要素でのみ機能する可能性があるため、これは必須です。

これは私に混乱を引き起こしているコードです:

(function($) {   
    var methods = {
        init: function(options) {
        // Maintain chainability
            return this.each(function () {
                var me;
                if($(this).prop('tagName') != 'P')
                {   $(this).append('<p></p>');
                    me = $(this).children('p');
                }
                else me = $(p);
            // The following 2 lines error (I was desperate)
                $(this) = me;
                this = me;
            // The following line does nothing (that I can tell)
                return me;
            });
        },
        ... other methods ...
    };
    $.fn.Plugin = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
        // Run Init
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery Plugin');
        }
    };
}
(jQuery));

また、init 関数内でリストを再作成して、新しく作成された<p>s のみを取得するようにしました。誰かが私を正しい方向に導くための有効な提案を持っていますか?

注:上記のコードの方が効率的であることは承知しています...問題を解決するために、わかりやすくするために分割しています。

4

2 に答える 2

2

の戻り値this.eachは常にthis変更不可能であり、あなたの場合は.Plugin()を呼び出す選択された要素のリストです。あなたの場合、選択された要素のリストを単に返すのではなく、変更されたリストを返したいと思います。(.eachループ内のリターンがthis.each自体のリターンに影響を与えることを何もしていないことは100%正しいです。)

ループの外側で変数を定義してthis.eachdom要素の新しいリストを収集し、ループの内側に正しいdom要素を追加して(注1を参照)、ループの外側の要素の新しいリストを返すと、必要な結果が表示されます。 。ただし、ここにはいくつかの落とし穴があります。

注1:プラグイン処理にthis.eachを使用する理由は、セレクターが複数の要素を返す可能性があるためです。非pタグが含まれている場合は常に、選択されたセレクターとは異なる要素のセットを基本的に返すため、要素の新しいリストを収集する必要があります。考慮すべきケースは$('div.myDiv, p.myP').Plugin()、異なるタグタイプを持つ複数の要素を選択することです。

主な落とし穴の1つは、選択する要素にスタイルを設定したり、プラグインが接続されているdom要素を識別するためにIDを使用したりすることがよくあることです。プラグインのルートであるdom要素を変更することにより、cssまたはidの場所に多くの問題が発生する可能性があり、これらの問題に対処するか、少なくとも考慮する必要があります。

(特に、すでに使用しているものを変換する場合と、他の人が一般的に使用するプラグインを作成する場合は、それができないことを示唆しているわけではありません。多くの厄介な問題が発生するだけです。)

(function($) {   
    var methods = {
        init: function(options) {
            var mes;
            this.each(function () {
                var me;
                if($(this).prop('tagName') != 'P')
                {   $(this).append('<p></p>');
                    me = $(this).children('p');
                }
                else me = $(p);
            }
            mes.push(me);
            return mes;
        },
        ... other methods ...
    };
    $.fn.Plugin = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
        // Run Init
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery Plugin');
        }
    };
}
(jQuery));
于 2013-03-15T14:39:45.380 に答える
1

purgatory101が述べたように、ここには実際には 2 つの問題があります。$().each()1 つ目は、独自の戻り値があることを理解することです。2 つ目は連鎖可能性です。$().each()の戻り値を克服するのはかなり簡単です。$().each()別のまたはjQueryオブジェクト配列を提供する必要があるだけです。連鎖可能性は、あなた/あなたのユーザーが必要/期待するものに帰着します。

jQuery とチェーン可能性

が頻繁に使用される性質上$().each()、ほとんどの場合、連鎖可能性は返される元の jQuery オブジェクトの連鎖可能性を指すと想定されています。ただし、チェーンが別の要素によって継続される jQuery コア内には、いくつかの状況があります。それはすべて、プラグインの最も可能性の高い使用に帰着します. 以下は、jQuery が使用する 2 つの最も一般的なチェーンです。

例 1: 結果指向リンク (ROL)

.add()を使用すると、元からではなく、結果からチェーンを継続できます。ユーザーが新しく追加された要素を変更することを前提としています。より一般的な例は.parent().children()ですが、これらは自明であり、当然のことながら、適切な名前の要素で作業したいと思うでしょう。

例 2: オリジン指向リンク (OOL)

.append()は元のオブジェクトを返します。.add()これは、同様の目的を達成するという点で に直接対応しますが、異なる値を返します。これは、データ、スタイル、および要素を変更するメソッドの大部分が使用するものです。

OOLソリューション

プラグインには多くのメソッドがあることが多いため、それらのメソッドを連鎖できることが重要です。OOL では、解決策は、毎回子のセットを一貫して生成する手順を考え出すこと<p>です。これは次のように行われます。

(function($) { 
// Search function
    var findP = function(obj) {
        // ... Search function for your <p> in THIS object
        return p;
    };
    var methods = {
        init: function(options) {
        // Maintain chainability
            return this.each(function () {
                var me;
                if($(this).prop('tagName') != 'P')
                {   $(this).append('<p></p>');
                    me = $(this).children('p');
                }
                else me = $(p);

                // ... other functionality...
            });
        },
        other1: function() {
            var searchMe = findP;
            return this.each(function() {
                var me = searchMe($(this));
            });
        }
    };
    $.fn.Plugin = function (method) {
        ... Route to method ...
    };
}
(jQuery));

これに関する問題は、元のオブジェクトがメソッド呼び出し間で変更された可能性があるため、それらが存在しない可能性を考慮する必要があることです。これはプロセッサの負荷が少し高くなりますが、より安全で、期待される動作に適合する可能性があります。

ROL ソリューション

ROL は、結果がすぐに適用される場合にのみ使用してください。.addこれは、jQuery の、.childrenおよび と同じ精神を保ち.parentます。これを実現するには、いくつかの方法があります。ここで懸念されるのは、これはさまざまな方法で実現できるものの、purgatory101 のプッシュによる解決策が最も安全だということです。別の $() リストを使用するショートカットは魅力的かもしれませんが、操作したくない要素を取得する危険性があるため、言及する必要があります。

    var methods = {
        init: function(options) {
        // Option 1) Build new list
            return newlist.each(function () {
                var me;
                if($(this).prop('tagName') != 'P')
                {   $(this).append('<p></p>');
                    me = $(this).children('p');
                }
                else me = $(p);

                // ... other functionality...
            });
        },
        // ... other methods ...
    };
    $.fn.Plugin = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
        // ... OR Option 2) build new list ...
            return methods.init.apply(newlist, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery Plugin');
        }            
    };

2つのオプションの違いがあるかどうかはわかりません。

于 2013-03-15T16:47:12.353 に答える