Ext.DD 子模块是很好的对拖放这样一个实现起来很麻烦的功能的封装,架构很清晰,接口很明确.最终使用 DropZone 与 DragZone即可.
----------------------------
DragDrop
DDTarget
DropTarget
DropZone
-----------------------------
DragDrop
DD
DDProxy
DragSource
DragZone
官方单独使用的例子比较少,今天阅读拖放模块源代码后,稍微熟悉一下与拖放模块的交互接口,写了个单独使用的例子:
jquery portal 比较:(转自javaeye网友)
细节体会:
1. Ext.DD 没有采用事件机制,仅仅采用 override 方法来实现通知。
2. DropZone 有容器以及容器内多个可drop区域的概念,容器通过 notifyOver 再通知各个 drop 区域,在每个通知中我们只需考虑当前是否在单个drop子区域并进行处理,不需要考虑整个容器,而注册时只需要对容器进行拖放注册,只需指明哪些属于应该关注的子区域, 基本上还是事件委托的理念,不用对个个子区域监听mousedown事件,改做容器监听。
3. Jquery 方式可见没有采用事件委托,对每个子区域都单独定义了拖放事件,并且也没有公用拖放代理对象,可见Ext.DD当拖放对象极多时还是性能应该会更好一点。
4. 例子expamles/dd/dragdropzones.js 存在bug :
getDragData: function(e) { var sourceEl = e.getTarget(v.itemSelector, 10); if (sourceEl) { d = sourceEl.cloneNode(true); d.id = Ext.id(); return v.dragData = { sourceEl: sourceEl, repairXY: Ext.fly(sourceEl).getXY(), ddel: d, patientData: v.getRecord(sourceEl).data } } },
ddel 当 invalid drag drop时,会发生 ddel.highlight 。
若传 d 则 highight 不会有效果(在复制节点上)。
修正:
var sourceEl = e.getTarget(v.itemSelector, 10); if (sourceEl) { return v.dragData = { sourceEl: sourceEl, repairXY: Ext.fly(sourceEl).getXY(), ddel: sourceEl, patientData: v.getRecord(sourceEl).data } }
其实 DragZone 已经clone了:
onInitDrag : function(x, y){ this.proxy.update(this.dragData.ddel.cloneNode(true)); this.onStartDrag(x, y); return true; },
但是做的不好,可能clone出重复 id 节点。
修正:
onInitDrag : function(x, y){ var t=this.dragData.ddel.cloneNode(true); t.id=Ext.id();// prevent duplicate ids this.proxy.update(t); this.onStartDrag(x, y); return true; },
extjs 例子没有修改 DragZone ,而为了防止重 id ,在例子中自己clone,但是失去了 highlight 的效果.