Jquery Draggable 和 Backbone.js 从可放置成功回调内部获取对骨干模型的引用

Posted

技术标签:

【中文标题】Jquery Draggable 和 Backbone.js 从可放置成功回调内部获取对骨干模型的引用【英文标题】:Jquery Draggable and Backbone.js getting reference to backbone model from inside the droppable success callback 【发布时间】:2011-11-11 19:09:19 【问题描述】:

我有一个主干视图模型,我在这里渲染它并使它可以用 jquery ui 拖动。

render: ->
$(this.el).attr('class', 'item').html(this.template(this.options.model.toJSON() ))
viewmodel = this
$(this.el).draggable
    revert: true
    drag: () ->
        console.log(viewmodel)

上面,我有可用的视图模型,可以将其从 dom 中删除,调用其模型上的方法等。但我想要将此视图模型拖到可放置的容器中 - 就像垃圾桶一样 - 然后调用一些视图模型的方法并将其从 DOM 中删除。

我看到的是,当一个项目被放入容器时的回调方法是:

$(function() 
    $("#trash").droppable(
        drop: function(event, ui) 
          console.log(ui.draggable);
        
    );
);

所以,我可以看到 ui.draggable 并将其从 DOM 中删除,但我没有参考它的视图模型。难道我做错了什么?有什么办法可以解决这个问题?

【问题讨论】:

【参考方案1】:

我想我遇到了同样的问题;我没有将元数据添加到元素或将其全局存储,而是将对实际视图本身的引用存储在 DOM 元素上,然后您可以访问模型以及您需要的任何信息。

window.MyDraggableView = Backbone.View.extend(
    initialize: function()
        $(this.el).draggable();
        $(this.el).data("backbone-view", this);
    
);

window.MyDropTarget = Backbone.View.extend(
    initialize: function()
        $(this.el).droppable(
            drop: function(ev, ui)
                // get reference to dropped view's model
                var model = $(ui.draggable).data("backbone-view").model;
            ,
        );
    ,
);

【讨论】:

这是 imo 最好的方法 我喜欢这个答案。但它会在大多数浏览器上正确收集垃圾吗(因为有循环引用)? 我不是 100% 确定,但我认为 JS 对象和 DOM 节点之间的循环引用只是旧 IE(7 及以下)的问题。不过,这可能值得研究。另外我认为 jQuery 数据也可以缓解这个问题。 这不是脱离了 Backbone.js 框架吗?【参考方案2】:

我遇到过这个问题。我因此解决了它:为放置目标提供对模型集合的引用。在可拖动对象上设置属性data-cid="<%= cid %>"。现在您可以从$(ui.draggable).data('cid') 中查找集合中的模型。由于主干断言 CID 是唯一的,因此您甚至可以扫描集合的集合,以防有多个模型类您想被丢弃。

【讨论】:

所以我可以获取集合中的项目,但是获取视图模型本身呢?运行 collection.remove(id) 会将其从集合中删除,但不会从我的视图中删除。 将集合上的 'remove' 事件绑定到从 DOM 中删除视图的视图方法。 您必须跟踪视图,将它们放入数组或 CID 跟踪的对象中。 非常感谢。这完全有效,并且以我看待 javascript 的方式改变了游戏规则。 :)【参考方案3】:

我使用的方法是通过自定义事件将事件从droppable传递到draggable。

var DroppableView = Backbone.View.extend(
  events:  'drop': 'dropHandler' ,
  initialize: function()  this.$el.droppable(); ,
  dropHandler: function(e, ui)  ui.draggable.trigger('drop:dropview'); 
)

var DraggableView = Backbone.View.extend(
  events:  'drop:dropview': 'dropviewDropHandler',
  initialize: function() this.$el.draggable(); ,
  dropviewDropHandler: function()  this.doSomething(); 
);

这让您在拖动视图的上下文中执行放置处理程序,这通常比在可放置视图的上下文中执行更有用。

【讨论】:

+1 的想法是让它在可拖动而不是可放置的上下文中执行。 这当然是这个线程上最好的解决方案。您还可以将DroppableView 实例作为drop:dropview 的参数传递,dropviewDropHandler 将可以访问DroppableView 和 DraggableView` 实例。【参考方案4】:

我们通过放置在应用命名空间中的全局属性(称为拖动)解决了这个问题。

由于一次只有一个视图被拖拽,拖拽视图绑定到拖拽事件,并将自己的模型写入window.dragging。

当它被拖放到可拖放视图上时,该视图会通过该拖动变量获取当前的拖动模型。

顺便说一句,该属性可以更好地放置在全局可访问的应用程序命名空间中,而不是直接将其添加到 window.properties 中。这是我们应用程序中的 App.View.tool。

像这样:

dragging = null;

draggableview = new Backbone.View.extend(

    //...
    initialize: function() 

        //...
        $(this.el).bind("dragStart",
        function() 
            window.dragging = this.model;
        ,
        this);

        //remove reference for garbage collection purpose
        $(this.el).bind("dragStop",
        function() 
            delete window.dragging;
        ,
        this);
    ,

);

droppableview = new Backbone.View.extend(

    //...
    initialize: function() 

        //...
        $(this.el).bind("drop",
        function() 
            var draggedmodel = window.dragging;
            delete window.dragging;
            // for garbage collection purpose
            //do funky stuff
            alert("You dropped " + draggedmodel.get('title') + " on " + this.el.get('title'));
            //...
        ,
        this);
    ,
);

【讨论】:

以上是关于Jquery Draggable 和 Backbone.js 从可放置成功回调内部获取对骨干模型的引用的主要内容,如果未能解决你的问题,请参考以下文章

获取 JQuery ui.draggable 的属性

jQuery UI-Draggable 参数集合

包含到父级的JQuery Draggable和额外的一个

如何仅使用 Draggable 和 Droppable jQuery 从克隆中删除类?

jQuery UI 拖动(Draggable) - 事件

.draggable 的 Jquery .trigger('stop') 方法