【发布时间】:2014-12-01 14:18:25
【问题描述】:
我正在尝试使用jQuery Boilerplate 编写我的第一个插件。我遇到的问题是,一旦我尝试处理一个事件,我就无法访问this 范围,我认为是variable shadowing。这似乎是jQuery Boilerplate 的常见用例,所以我猜我做错了。
我在 SO 上发现了两个类似的问题:
- jQuery plugin object: attached an event handler via .on() and now have a scope issue of this. (the main plugin object) - 没有答案
- Javascript scoping Issue using JQuery Boilerplate - 不回答我的问题
我创建了一个最小示例来演示该问题。
HTML
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
插件
(function($, window, document, undefined) {
'use strict';
var pluginName = 'elementValueLog',
defaults = {};
function Plugin(element, options) {
this.element = element;
this.$element = $(element);
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
$.extend(Plugin.prototype, {
init: function() {
this.$element.on('click', this.doLog);
},
doLog: function() {
// HERE: I can't figure out how to access the Plugin "this" scope
// I want to be able to use "element", "$element", "settings", etc.
console.log(this.$element.val().trim());
}
});
$.fn[pluginName] = function(options) {
this.each(function() {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin(this, options));
}
});
return this;
};
}(jQuery, window, document, undefined));
使用插件
$(document).ready(function() {
$('li').elementValueLog();
});
解决方案
我更愿意将此添加为答案,但被标记为“重复”会阻止这种情况。在尝试了其他帖子答案中显示的几种方法后,我找到了解决方案。我个人认为我的问题足够具体,可以独立存在,因为另一篇文章中的“规范”答案非常广泛。
对于browsers that support bind,init 函数可以这样更改:
init: function() {
this.$element.on('click', this.doLog.bind(this));
},
因为我需要支持IE 8,所以我将使用jQuery.proxy:
init: function() {
this.$element.on('click', $.proxy(this.doLog, this));
},
然后doLog 函数可以引用this.element、this.$element、this.settings 等。
根据Jeff Watkins的回答:
init: function() {
var plugin = this;
var doLog = function() {
console.log(plugin.$element.val().trim());
};
this.$element.on('click', doLog);
},
此解决方案的优点是保留 this 上下文,同时允许访问插件的 this 上下文。
【问题讨论】:
-
所以这已被标记为另一个帖子的副本,但我不明白如何应用该帖子中提供的解决方案。
标签: javascript jquery jquery-boilerplate