我尝试使用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
新的this
。
没有理由以您所使用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()
then会返回该集合,并且插件应该是可链接的,因此您只需返回它即可。
一条经验法则是,如果要直接在插件内部传递this
jQuery工厂($()
)函数,那么您做错了什么,因为它已经是集合。根据经验,第二个规则,其目的除了那些几乎所有的插件定义返回有关元素的信息(如.val()
,.html()
或.text()
没有给予PARAM时)应与启动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));
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句