繁体   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