ExtJS 4.0+移除Ext.view.View.onClick方法後,導致拖拽操作時若未先點擊,view.getSelectedNodes()返回空數組的經典問題。本文提供官方推薦的替代方案與最佳實踐。
在實現DataView/Grid拖拽功能時,常見代碼模式:
// 舊代碼(ExtJS 3.x)
view.onClick = function(e) {
// 自定義點擊邏輯
this.getSelectedNodes(); // 依賴內部選中狀態
};
ExtJS 4+重寫事件系統,onClick不再暴露,直接覆蓋會破壞內部選中邏輯。
利用事件對象e.getTarget()獲取點擊元素,手動維護選中狀態:
// 在拖拽開始事件(如beforedrag)中處理
var sourceEl = e.getTarget('.thumb-wrap'); // 或 Ext.getCmp(id)
// 拖拽對象
if (sourceEl) {
var selectedNodes = this.view.getSelectedNodes();
// 關鍵:若無選中行,將點擊元素加入選中集合
if (selectedNodes.length < 1) {
selectedNodes.push(sourceEl);
}
// 後續拖拽邏輯使用 selectedNodes
}
Ext.define('My.view.DraggableDataView', {
extend: 'Ext.view.View',
alias: 'widget.draggableview',
initComponent: function() {
this.plugins = [{
ptype: 'dataviewdragdrop',
dragGroup: 'myGroup',
dropGroup: 'myGroup'
}];
this.callParent();
},
listeners: {
beforedrag: function(dragZone, e) {
// 核心修復:確保有選中節點
var sourceEl = e.getTarget(this.itemSelector);
if (sourceEl) {
var selected = this.getSelectedNodes();
if (selected.length === 0) {
selected.push(sourceEl);
}
}
},
drop: function(node, data, overModel, dropPosition, eOpts) {
// 獲取拖拽的記錄
var records = data.records;
// 業務邏輯處理
}
}
});
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| e.getTarget()手動選中 | 官方推薦、無侵入、兼容性好 | 需在各拖拽事件中重複代碼 | 大多數場景 |
| 覆蓋onItemClick | 集中處理點擊邏輯 | 需深度理解內部實現、升級風險大 | 複雜自定義選中邏輯 |
| 使用SelectionModel API | 標準API、功能完整 | 學習成本高、配置繁瑣 | Grid、Tree等複雜組件 |