我刚刚为此编写了一个 jQuery 插件。它还使用.data() 方法。
注册:
我已经包装/代理了 Backbone View setElement 方法以将所需数据附加到视图的 $el 属性。
注册是在幕后完成的如下:
$(myViewsEl).backboneView(myView);
检索:
插件向上遍历 DOM 层次结构(使用 .closest()),直到找到具有所需数据条目的元素,即具有关联视图的 DOM 元素:
var nearestView = $(e.target).backboneView();
此外,我们可以指定我们希望获得什么类型的 Backbone View,继续向上层级,直到找到匹配类型的实例:
var nearestButtonView = $(e.target).backboneView(ButtonView);
JSFiddle 示例:
可以找到here。
注意事项:
我希望我认为这里没有内存泄漏是正确的;如果第二次调用setElement,则会执行“取消链接”,因为删除视图的元素默认调用.remove(),这也会破坏所有数据。如果您有不同的想法,请告诉我。
插件代码:
(function($) {
// Proxy the original Backbone.View setElement method:
// See: http://backbonejs.org/#View-setElement
var backboneSetElementOriginal = Backbone.View.prototype.setElement;
Backbone.View.prototype.setElement = function(element) {
if (this.el != element) {
$(this.el).backboneView('unlink');
}
$(element).backboneView(this);
return backboneSetElementOriginal.apply(this, arguments);
};
// Create a custom selector to search for the presence of a 'backboneView' data entry:
// This avoids a dependency on a data selector plugin...
$.expr[':'].backboneView = function(element, intStackIndex, arrProperties, arrNodeStack) {
return $(element).data('backboneView') !== undefined;
};
// Plugin internal functions:
var registerViewToElement = function($el, view) {
$el.data('backboneView', view);
};
var getClosestViewFromElement = function($el, viewType) {
var ret = null;
viewType = viewType || Backbone.View;
while ($el.length) {
$el = $el.closest(':backboneView');
ret = $el.length ? $el.data('backboneView') : null;
if (ret instanceof viewType) {
break;
}
else {
$el = $el.parent();
}
}
return ret;
};
// Extra methods:
var methods = {
unlink: function($el) {
$el.removeData('backboneView');
}
};
// Plugin:
$.fn.backboneView = function() {
var ret = this;
var args = Array.prototype.slice.call(arguments, 0);
if ($.isFunction(methods[args[0]])) {
methods[args[0]](this);
}
else if (args[0] && args[0] instanceof Backbone.View) {
registerViewToElement(this.first(), args[0]);
}
else {
ret = getClosestViewFromElement(this.first(), args[0]);
}
return ret;
}
})(jQuery);