簡體   English   中英

帶有原型的jQuery插件

[英]Jquery plugin with prototype

我嘗試使用Jquery插件的基礎知識和原型概念,但最終出現了異常行為。

HTML:

<div>
    <span>
        <textarea>Text Area with 500 characters. Adding Some text.</textarea>
        <span class="cl"></span>
    </span>
    <span>
        <textarea>Text Area with 100 characters</textarea>
        <span class="cl"></span>
    </span>
</div>

jQuery的:

(function ($) {
    var tisCharsLeftCntxt = null;

    function fnCharsLeft(ele, genStngs) {
        this.jqe = $(ele);
        this.maxChars = genStngs.maxChars;
        tisCharsLeftCntxt = this;
        this.fnInit();
    }
    fnCharsLeft.prototype = {
        fnInit: function () {
           tisCharsLeftCntxt.fnUpdateRemainingChars();
            tisCharsLeftCntxt.jqe.keyup(function (event) {
                key = event.keyCode ? event.keyCode : event.which;
                if ((37 != key) && (38 != key) && (39 != key) && (40 != key)) {
                    tisCharsLeftCntxt.fnUpdateRemainingChars();
                }
            });
        },
        fnUpdateRemainingChars: function () {
            var charsLft = tisCharsLeftCntxt.maxChars - tisCharsLeftCntxt.jqe.val().length,
                jqeDestToUpdt = tisCharsLeftCntxt.jqe.siblings('.cl');
            charsLft = (charsLft < 0) ? 0 : charsLft;
            if (charsLft) {
                jqeDestToUpdt.text(charsLft + ' more of ' + tisCharsLeftCntxt.maxChars + ' characters');
            } else {
                tisCharsLeftCntxt.jqe.val(tisCharsLeftCntxt.jqe.val()
                    .substring(0, tisCharsLeftCntxt.maxChars));
                tisCharsLeftCntxt.jqe.scrollTop(tisCharsLeftCntxt.jqe[0].scrollHeight);
                jqeDestToUpdt.text("Maximum limit of " + tisCharsLeftCntxt.maxChars + " characters reached");
                return false;
            }
        }
    };
    $.fn.fnCharsLeftPlgn = function (genStngs) {
        return $(this).data("charsleft", new fnCharsLeft(this, genStngs));
    };
})(window.jQuery);
$('div span:nth-child(1) textarea').fnCharsLeftPlgn({maxChars: 500});
$('div span:nth-child(2) textarea').fnCharsLeftPlgn({maxChars: 100});

小提琴: http : //jsfiddle.net/5UQ4D/&http : //jsfiddle.net/5UQ4D/1/

要求是,插件應顯示可以在文本區域中添加的字符數。 如果頁面中只有一個文本區域,則效果很好。 但是,如果有多個,則只有與插件最后關聯的文本區域可以正常工作。

關於此處的代碼,在初始化期間,兩個文本區域中剩余的字符數都已正確更新(僅第一次)。 但是稍后,當更改文本區域的內容時,只有第二個100個字符(或與插件關聯的最新文本區域)可以正常工作。

似乎,我無法將插件上下文單獨限制為一個文本區域。 請指教,..

問題一:

正如在評論中提到的,你要創建一個命名的變量tisCharsLeftCntxt其他環境之外,然后分配this在你的構造吧。 每次運行插件時,您tisCharsLeftCntxt使用新的thistisCharsLeftCntxttisCharsLeftCntxt

沒有理由以您所使用的批發方式this進行引用。 您的代碼中只有一個地方范圍發生變化, this不再是您的實例。 該位置在keyup事件處理功能的內部。 你應該你的別名本地化this只是其中包含事件處理程序的方法。

問題2:

我相信問題的另一部分(如果您對匹配多個元素的選擇器運行該插件,將會看到此問題)在插件函數內部(該函數$.fn )。

$.fn.fnCharsLeftPlgn = function (genStngs) {
    return $(this).data("charsleft", new fnCharsLeft(this, genStngs));
};

它應該是:

$.fn.fnCharsLeftPlgn = function (genStngs) {
    return this.each(function () {
        $(this).data("charsleft", new fnCharsLeft(this, genStngs));
    });
};

當直接在已添加到jQuery原型( $.fn )中的方法內部時, this指的是當前集合的整體,而不是元素。 一個插件應each本身以針對其各個成員運行元件的特定邏輯。

如果不使用.each()您所呼叫.data()對整個集合,其所有的設置charsleft數據屬性的一個實例fnCharsLeft 通過使用.each()您可以為fnCharsLeft中的每個元素創建.each()的新實例。

由於.each()然后返回集合,並且插件應該是可鏈接的,因此您只需返回它。

一條經驗法則是,如果你傳遞this到jQuery的工廠( $()直接在插件內,函數,那么你所做的是錯的,因為它已經集合。 作為第二個經驗法則,除旨在返回有關元素的信息(例如,在未提供參數的情況下, .val() .html().text()那些插件定義之外),幾乎所有插件定義都應以return this.each(function() {...開頭return this.each(function() {...

解決方案:

將這些更改匯總在一起將產生以下錯誤: http : //jsfiddle.net/5UQ4D/4/

這段代碼:

(function ($) {
    var fnCharsLeft = function (ele, genStngs) {
        this.jqe = $(ele);
        this.maxChars = genStngs.maxChars;
        this.fnInit();
    };
    fnCharsLeft.prototype = {
        fnInit: function () {
            var instance = this;

            this.fnUpdateRemainingChars();
            this.jqe.on('keyup', function (e) {
                key = e.keyCode ? e.keyCode : e.which;

                if (37 != key && 38 != key && 39 != key && 40 != key) {
                    instance.fnUpdateRemainingChars();
                }
            });
        },
        fnUpdateRemainingChars: function () {
            var charsLft = this.maxChars - this.jqe.val().length,
                jqeDestToUpdt = this.jqe.siblings('.cl');

            charsLft = charsLft < 0 ? 0 : charsLft;

            if (charsLft) {
                jqeDestToUpdt.text(charsLft + ' more of ' + this.maxChars + ' characters');
            } else {
                this.jqe
                    .val(this.jqe.val().substring(0, this.maxChars))
                    .scrollTop(this.jqe[0].scrollHeight);

                jqeDestToUpdt.text("Maximum limit of " + this.maxChars + " characters reached");

                return false;
            }
        }
    };

    $.fn.fnCharsLeftPlgn = function (genStngs) {
        return this.each(function () {
            $(this).data('charsleft', new fnCharsLeft(this, genStngs));
        });
    };
}(window.jQuery));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM