javascript Backbone.js - 给定一个元素,我如何获得视图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5013848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Backbone.js - Given an element, how do I get the view?
提问by a paid nerd
I've created a bunch of Backbone.jsviews. Each view has an associated element (view.el).
我创建了一堆Backbone.js视图。每个视图都有一个关联的元素 ( view.el)。
Given an element on the page — out of context of the view — what would be the best way to get the view for the element?
给定页面上的一个元素——脱离视图的上下文——获取该元素的视图的最佳方式是什么?
For example, say some event affects a bunch of elements on a page and I want to call a method on every view associated with the affected elements.
例如,假设某个事件影响页面上的一堆元素,我想在与受影响元素关联的每个视图上调用一个方法。
One way would be to assign the view to the element's data, but I'm wondering if I've missed something smarter:
一种方法是将视图分配给元素的数据,但我想知道我是否错过了更聪明的东西:
var myview = BackBone.View.extend({
initialize: function(options) {
$(this.el).data('view', this);
...
}
});
(I'm using Backbone with jQuery 1.5.)
(我在 jQuery 1.5 中使用 Backbone。)
采纳答案by Ed .
I've just written a jQuery plugin for this. It also uses the .data()method.
我刚刚为此编写了一个 jQuery 插件。它也使用该.data()方法。
Registration:
登记:
I have wrapped / proxied the Backbone View setElementmethod to attach the required data to the view's $elproperty.
我已经包装/代理了 Backbone ViewsetElement方法以将所需的数据附加到视图的$el属性。
Registration is done behind the sceneslike so:
注册是在幕后完成的,如下所示:
$(myViewsEl).backboneView(myView);
Retrieval:
恢复:
The plugin traverses up the DOM hierarchy (using .closest()) until it finds an element with the required data entry, i.e a DOM element with an associated view:
该插件向上遍历 DOM 层次结构(使用.closest()),直到找到具有所需数据条目的元素,即具有关联视图的 DOM 元素:
var nearestView = $(e.target).backboneView();
In addition, we can specify what type of Backbone View we wish to obtain, continuing up the hierarchy until we find an instance of matching type:
此外,我们可以指定我们希望获得什么类型的 Backbone View,继续沿层次结构直到我们找到匹配类型的实例:
var nearestButtonView = $(e.target).backboneView(ButtonView);
JSFiddle Example:
JSFiddle 示例:
Can be found here.
可以在这里找到。
Notes:
笔记:
I hope I am correct in thinking there are no memory leaks involved here; An 'unlink' is performed if setElementis called a second time round, and since removing a view's element calls .remove()by default, which destroys all data as well. Let me know if you think differently.
我希望我认为这里不涉及内存泄漏是正确的;如果setElement第二次调用,则执行“取消链接” ,并且由于.remove()默认情况下删除视图的元素调用,这也会破坏所有数据。如果您有不同的想法,请告诉我。
The plugin code:
插件代码:
(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);
回答by Bill Eisenhauer
Every view can register for DOM events. As such, every view with the kind of element that you are interested in should register for the DOM event and then assign an event-responding function that does what you want. If you need to DRY things up, use mixin techniques to mix in the function.
每个视图都可以注册 DOM 事件。因此,每个包含您感兴趣的元素类型的视图都应该注册 DOM 事件,然后分配一个事件响应函数来执行您想要的操作。如果您需要干掉事情,请使用 mixin 技术来混合函数。
I think maybe this solution is easier than you may have initially imagined. Just let the views do the work that they are intended to do.
我认为这个解决方案可能比您最初想象的要容易。只需让视图做他们打算做的工作。
回答by Mario
You could maintain a views hash (dictionary) that uses the element as the key and returns the view (or views).
您可以维护使用元素作为键并返回视图(或视图)的视图哈希(字典)。
回答by Vlad Gurovich
Since every view has a reference to the model its displaying, what I would do is assign id of the model to the view's associated element(hopefuly that is not affected by the changes by outside event). Also make sure that the model has a reference to its view. Then have these models stored in a Backbone collection.
由于每个视图都有对其显示的模型的引用,我要做的是将模型的 id 分配给视图的关联元素(希望不受外部事件更改的影响)。还要确保模型有对其视图的引用。然后将这些模型存储在 Backbone 集合中。
With this setup, once something happens to an element, you use the elements id to retrieve corresponding model from Backbone collection that you created above and then this model will give you your view reference.
通过这种设置,一旦某个元素发生某些事情,您就可以使用元素 id 从您在上面创建的 Backbone 集合中检索相应的模型,然后该模型将为您提供视图参考。
回答by Louis
I've been using a method inspired by Ed's solutionbut it does not require the use of jQuery. It does two things:
我一直在使用一种受Ed 解决方案启发的方法,但它不需要使用 jQuery。它做两件事:
It sets the attribute
data-backbone-viewon the root elements of all views. This is convenient when looking at the DOM tree in a debugger. You can immediately see which elements are associated with views. You can also use the CSS selector[data-backbone-view]to find elements that are the roots of Backbone views.It adds a
backboneViewproperty to each root element of a view. It is then possible to get from the DOM element to the view by looking a the DOM element's properties.
它
data-backbone-view在所有视图的根元素上设置属性。这在调试器中查看 DOM 树时很方便。您可以立即看到哪些元素与视图相关联。您还可以使用 CSS 选择器[data-backbone-view]来查找作为 Backbone 视图根的元素。它
backboneView为视图的每个根元素添加一个属性。然后可以通过查看 DOM 元素的属性从 DOM 元素获取视图。
I turn this on only when I'm debugging. Here is the code:
我只在调试时打开它。这是代码:
var originalSetElement = Bb.View.prototype.setElement;
Bb.View.prototype.setElement = function setElement(element) {
if (this.el && this.el !== element) {
delete this.el.backboneView;
}
element.backboneView = this;
element.setAttribute("data-backbone-view", "true");
return originalSetElement.apply(this, arguments);
};

