jQuery扩展和闭包
jQuery extension and closures
我正在学习javascript,并且我正在尝试学习更多关于jQuery的知识。我在JS中创建了一个非常简单的"表单控制器",所以当我创建传递表单作为参数的对象时,它会连接事件并劫持提交:
var FormController = function (form) {
// private field
var _form = $(form);
var _url = _form.attr('action');
var _isValid = false;
$(form).submit(function (e) {
submitForm();
e.preventDefault();
});
var disableAll = function () {
_form.find('select,input,textarea').attr('disabled', 'disabled')
};
var enableAll = function () {
_form.find('select,input,textarea').removeAttr('disabled')
};
var submitForm = function () {
disableAll();
_isValid = true;
if (_isValid) {
$.ajax({
url: _url,
type: 'POST',
success: function (data, textStatus, jqXHR) {
enableAll();
var obj = jQuery.parseJSON(jqXHR.responseText);
print(data.Result ? data.Result : "[No Result]");
print(textStatus.toString());
},
error: function (data, textStatus, jqXHR) {
print(textStatus);
_form.css('border', '1px solid Red');
enableAll();
}
});
}
};
// public fields and functions
return {
getIsValid: function () { return _isValid; },
submit: function () { return submitForm(); }
};
};
按预期工作。现在我想创建一个jQuery扩展,这样我就可以将该对象应用于结果:
$.fn.formController = function () {
return this.each(function (i, item) {
new FormController(item);
});
};
我也像预期的那样工作,但是…GC会收集该对象吗?还是因为事件是连接的,所以它被视为引用?
现在,我想保持控制器的实例可用,这样我就可以在创建后操作它们,例如调用方法。像这样:
$('#myForm').formController('submit');
我试了好几种方法做这件事,但我都做不到。我试着用一个跟踪项目等的对象放一个闭包。但我只是搞砸了"这个"。
正确的做法是什么?我想,到目前为止,我所做的一切都可能是错误的,即使它有效。
谢谢。
如果问题不够清楚,我很抱歉。我的目标是一种方式,我可以这样做:$('#myForm').formController('submit');
,然后函数将找到与该HTML对象关联的"FormController"对象,并调用这个"提交"成员。
我想实现这样的东西:
$.fn.formController = function (name) {
if(!document._items)
document._items = [];
if (name) {
return this.each(function (i, item) {
var id = $(item).data('form-controller');
if (id) {
var fc = document._items[id];
var member = fc[name];
if (member) {
if (typeof member == 'function')
member();
}
}
});
}
else {
return this.each(function (i, item) {
var id = document._items.push(new FormController(item)) - 1;
$(item).data('form-controller', id.toString());
});
}
};
这种方法的问题是,我保持一个集合作为全局对象,我想要的是使其内部。我尝试过闭包,但我只遇到了"this"(指向DOMwindow)或"_items"var为空的问题。
正确的方法是什么?
您可以使用jQuery UI的Widget工厂,它为您提供了开箱即用的功能:
$.widget("vtortola.formcontroller", {
_create: function() {
// Use `this.element` to initialize the element.
// You can also use this.options to get the options object that was passed.
},
_destroy: function() {
// You can unbind events here to remove references from the DOM, so is'll get
// deleted by the garbage collector.
},
submit: function() { /* ... */ }
});
// Example
$('#form').formcontroller({foo: 123}); // Calls `_create()` with the supplied options
$('#form').formcontroller('submit'); // Calls the `submit` method
小部件工厂还提供了选项setter/getter、默认选项和其他很酷的东西。有关更多细节,请参阅官方文档和教程bililite。如果你不使用jQuery UI做其他事情,你可以单独使用小部件工厂代码,它不依赖于jQuery UI的其他部分。
如果您不喜欢使用jQuery UI的小部件工厂,您可以直接将对象存储在.data()
上(这也是小部件工厂所做的),不需要保存它们的集合并手动跟踪它们。你的代码应该是这样的:
$.fn.formController = function () {
var args = arguments;
return this.each(function (i, item) {
var $this = $(this), _obj;
// When calling `$(..)`.formController() with arguments when the object already
// exists, it treats the first argument as the method name and passes the rest
// as arguments to that method.
if (arguments.length && (_obj = $this.data('FormController'))) {
_obj[args[0]].apply(_obj, Array.prototype.slice.call(args, 1));
} else {
$this.data('FormController', new FormController(item));
}
});
};
use
(function($){
$.fn.formController = function(parameter1, parameter2){
//this = #myForm
}
)(jQuery);
我也尝试过创建一个集合作为函数本身的属性。
它可以工作,但我不知道它是否正确/合适:D
$.fn.formController = function (name) {
if (name) {
return this.each(function (i, item) {
var id = $(item).data('form-controller');
if (id) {
var fc = $.fn.formController.Items[id];
print('get: ' + id + ' ' + (fc?'found':'not found'));
var member = fc[name];
if (member) {
if (typeof member == 'function')
member();
}
}
});
}
else {
return this.each(function (i, item) {
var id = $.fn.formController.Items.push(new FormController(item)) - 1;
print('add: ' + id);
$(item).data('form-controller', id.toString());
});
}
};
$.fn.formController.Items = [];
- 在underscorejs模板中使用闭包
- setTimeout可以与闭包内的函数一起使用吗
- 附加到原型属性的Do函数没有闭包
- 使用闭包共享构造函数参数
- 使用Google闭包编译器包含一个Ecmascript 6类
- 从js引擎的角度来看闭包和构造函数是如何工作的
- for循环中的JavaScript闭包
- Javascript闭包-如何防止内存泄漏
- 子类访问父类's闭包变量
- 闭包如何具体化数据封装
- Javascript.闭包和dynamic'这'实际上具有约束力
- 构造函数函数闭包变量
- 闭包js框架-将ArrayBuffer转换为字符串
- jQuery扩展对以前闭包的复制
- 如何使用闭包编译器在 javascript 中注释扩展泛型类型的类
- 使用 fn.extend() 和 Google 闭包编译器扩展 jQuery
- 使用闭包编译器时扩展错误
- 如何在javascript中扩展抽象类,并为闭包编译器进行注释,但不使用闭包库
- jQuery扩展和闭包
- 为什么谷歌闭包编译器在扩展Date()的ES6对象上失败