【问题标题】:Backbone.js - Given an element, how do I get the view?Backbone.js - 给定一个元素,我如何获得视图?
【发布时间】:2011-02-16 07:54:58
【问题描述】:

我创建了一堆 Backbone.js 视图。每个视图都有一个关联元素 (view.el)。

给定页面上的一个元素——脱离视图的上下文——获取该元素的视图的最佳方式是什么?

例如,假设某个事件影响了页面上的一堆元素,我想在与受影响的元素关联的每个视图上调用一个方法。

一种方法是将视图分配给元素的数据,但我想知道我是否错过了一些更聪明的东西:

var myview = BackBone.View.extend({
    initialize: function(options) {
        $(this.el).data('view', this);
        ...
    }
});

(我在 jQuery 1.5 中使用 Backbone。)

【问题讨论】:

  • 您有问题的上下文吗?也许您可以通过其他方式实现您想要做的事情。
  • 你不能从受影响的元素中触发一个自定义的 jquery 事件,它会冒泡到你的视图中并且你可以捕捉到吗?

标签: javascript jquery backbone.js


【解决方案1】:

我刚刚为此编写了一个 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);

【讨论】:

    【解决方案2】:

    每个视图都可以注册 DOM 事件。因此,每个具有您感兴趣的元素类型的视图都应该注册 DOM 事件,然后分配一个事件响应函数来执行您想要的操作。如果你需要 DRY,可以使用 mixin 技术来混合函数。

    我认为这个解决方案可能比您最初想象的要容易。让视图做它们打算做的工作。

    【讨论】:

    • 对于一长串 DOM 元素,使用事件委托来捕获 DOM 事件通常更高效。在这种情况下,视图可能不知道从其关联元素分派的事件,因为这些事件被一些父视图在冒泡链的上游捕获。在这种情况下,您需要父视图跟踪子视图元素并在捕获事件时匹配它们。
    • 这个答案的一个具有挑战性的场景是您在视图范围内保存一堆数据,然后允许用户在整个地方修改和拖放元素,移动例如,不同列表之间的项目。然后在最后你会想要询问一个项目列表来获取它的元素,将它们转换成视图,从视图中获取复杂的数据对象,并将所有内容作为 JSON 发送到服务器。在这种情况下,您几乎必须使用 .data() 将元素与元素相关联
    【解决方案3】:

    您可以维护一个以元素为键并返回视图(或多个视图)的视图哈希(字典)。

    http://www.timdown.co.uk/jshashtable/

    【讨论】:

      【解决方案4】:

      由于每个视图都有对其显示的模型的引用,我要做的是将模型的 id 分配给视图的关联元素(希望不受外部事件更改的影响)。还要确保模型具有对其视图的引用。然后将这些模型存储在 Backbone 集合中。

      通过此设置,一旦元素发生某些事情,您可以使用元素 id 从您在上面创建的 Backbone 集合中检索相应的模型,然后此模型将为您提供视图参考。

      【讨论】:

      • 一个模型不应该引用“它的”视图——模型可以在屏幕上以任意数量的方式表示,并且有任意数量的视图,因此模型和视图是分开的。
      【解决方案5】:

      我一直在使用一种受Ed's solution 启发的方法,但它不需要使用 jQuery。它做了两件事:

      1. 它在所有视图的根元素上设置属性data-backbone-view。这在调试器中查看 DOM 树时很方便。您可以立即查看哪些元素与视图相关联。您还可以使用 CSS 选择器 [data-backbone-view] 来查找作为 Backbone 视图根的元素。

      2. 它将backboneView 属性添加到视图的每个根元素。然后可以通过查看 DOM 元素的属性从 DOM 元素到视图。

      我只在调试时打开它。代码如下:

      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);
      };
      

      【讨论】:

        猜你喜欢
        • 2010-11-25
        • 2013-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 2011-10-19
        • 2014-09-22
        相关资源
        最近更新 更多