解决事件泄漏问题
This commit is contained in:
@@ -495,6 +495,8 @@ class DragStateManager {
|
||||
};
|
||||
this.isEnabled = true;
|
||||
this.debugMode = false;
|
||||
this.eventListenersRegistered = false; // 初始化监听器注册标志
|
||||
this.cleanupScheduler = null; // 初始化清理调度器
|
||||
|
||||
// 绑定方法
|
||||
this._onDragEvent = this._onDragEvent.bind(this);
|
||||
@@ -516,12 +518,24 @@ class DragStateManager {
|
||||
console.log('🎯 拖拽状态管理器初始化完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一的拖拽ID
|
||||
* @param {string} componentType - 组件类型
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
_generateDragId(componentType) {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substring(2, 9);
|
||||
return `${componentType}_${timestamp}_${random}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册事件监听器
|
||||
*/
|
||||
_registerEventListeners() {
|
||||
// 防止重复注册监听器
|
||||
if (this.eventListenersRegistered) {
|
||||
console.log('🚫 已经注册了监听器,跳过重复注册');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -537,17 +551,22 @@ class DragStateManager {
|
||||
dragEvents.forEach(eventType => {
|
||||
eventBus.on(eventType, this._onDragEvent, {
|
||||
priority: 1,
|
||||
deduplication: { type: 'EVENT_BASED', key: 'dragState' }
|
||||
deduplication: { type: 'EVENT_BASED', key: 'dragState' },
|
||||
componentId: 'drag-state-manager'
|
||||
});
|
||||
});
|
||||
|
||||
this.eventListenersRegistered = true;
|
||||
console.log('✅ 拖拽管理器事件监听器注册完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁管理器
|
||||
*/
|
||||
destroy() {
|
||||
// 取消所有拖拽
|
||||
this.cancelAllDrags();
|
||||
|
||||
// 清理事件监听器
|
||||
const dragEvents = [
|
||||
// Panel拖拽事件
|
||||
@@ -565,10 +584,17 @@ class DragStateManager {
|
||||
// 清理清理调度器
|
||||
this._stopCleanupScheduler();
|
||||
|
||||
// 清理拖拽状态
|
||||
this.dragStates.clear();
|
||||
// 清理数据
|
||||
this.activeDrags.clear();
|
||||
this.dragHistory = [];
|
||||
this.dragTargets.clear();
|
||||
|
||||
// 清理冲突检测器
|
||||
this.conflictDetector.activeDrags.clear();
|
||||
this.conflictDetector.conflictHistory = [];
|
||||
|
||||
this.isEnabled = false;
|
||||
this.eventListenersRegistered = false;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
|
||||
@@ -579,34 +605,66 @@ class DragStateManager {
|
||||
async _onDragEvent(data) {
|
||||
if (!this.isEnabled) return;
|
||||
|
||||
const monitorId = globalEventActions.startMonitor(`drag_${data.eventType || data.type}`);
|
||||
const monitorId = globalEventActions.startMonitor(`drag_${data.eventType}`);
|
||||
|
||||
try {
|
||||
const { eventType = data.type, dragId, componentType, sourceElement } = data;
|
||||
|
||||
// 从事件数据中提取 dragId,如果没有则根据组件类型推断
|
||||
let actualDragId = dragId;
|
||||
if (!actualDragId) {
|
||||
if (data.panelId) {
|
||||
actualDragId = `panel_${data.panelId}_${data.timestamp || Date.now()}`;
|
||||
} else if (data.tabIndex !== undefined) {
|
||||
actualDragId = `tabpage_${data.tabId}_${data.tabIndex}_${data.timestamp || Date.now()}`;
|
||||
} else if (data.areaId) {
|
||||
actualDragId = `area_${data.areaId}_${data.timestamp || Date.now()}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 推断组件类型
|
||||
let actualComponentType = componentType;
|
||||
if (!actualComponentType) {
|
||||
if (data.panelId) {
|
||||
actualComponentType = 'panel';
|
||||
} else if (data.tabIndex !== undefined) {
|
||||
actualComponentType = 'tabpage';
|
||||
} else if (data.areaId) {
|
||||
actualComponentType = 'area';
|
||||
}
|
||||
}
|
||||
|
||||
// 准备标准化的拖拽数据
|
||||
const dragData = {
|
||||
...data,
|
||||
dragId: actualDragId,
|
||||
componentType: actualComponentType,
|
||||
sourceElement: sourceElement || data.element
|
||||
};
|
||||
|
||||
switch (eventType) {
|
||||
case 'panel.drag.start':
|
||||
case 'tabpage.drag.start':
|
||||
case 'area.drag.start':
|
||||
await this._handleDragStart(data);
|
||||
await this._handleDragStart(dragData);
|
||||
break;
|
||||
|
||||
case 'panel.drag.move':
|
||||
case 'tabpage.drag.move':
|
||||
case 'area.drag.move':
|
||||
await this._handleDragMove(data);
|
||||
await this._handleDragMove(dragData);
|
||||
break;
|
||||
|
||||
case 'panel.drag.end':
|
||||
case 'tabpage.drag.end':
|
||||
case 'area.drag.end':
|
||||
await this._handleDragEnd(data);
|
||||
await this._handleDragEnd(dragData);
|
||||
break;
|
||||
|
||||
case 'panel.drag.cancel':
|
||||
case 'tabpage.drag.cancel':
|
||||
case 'area.drag.cancel':
|
||||
await this._handleDragCancel(data);
|
||||
await this._handleDragCancel(dragData);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -628,28 +686,31 @@ class DragStateManager {
|
||||
async _handleDragStart(data) {
|
||||
const { dragId, componentType, sourceElement, position, options = {} } = data;
|
||||
|
||||
// 如果没有提供 dragId,生成一个唯一的 dragId
|
||||
const actualDragId = dragId || this._generateDragId(componentType);
|
||||
|
||||
// 创建拖拽状态
|
||||
const dragState = new DragState(dragId, componentType, sourceElement, options);
|
||||
const dragState = new DragState(actualDragId, componentType, sourceElement, options);
|
||||
dragState.startPosition = { ...position };
|
||||
dragState.currentPosition = { ...position };
|
||||
dragState.status = 'active';
|
||||
|
||||
// 保存拖拽状态
|
||||
this.activeDrags.set(dragId, dragState);
|
||||
this.activeDrags.set(actualDragId, dragState);
|
||||
|
||||
// 注册到冲突检测器
|
||||
this.conflictDetector.registerDrag(dragState);
|
||||
|
||||
// 触发状态变更事件
|
||||
// 触发状态变更事件,包含 dragId
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, {
|
||||
dragId,
|
||||
dragId: actualDragId,
|
||||
newStatus: 'active',
|
||||
dragState: dragState.getSummary()
|
||||
});
|
||||
|
||||
// 发送初始反馈
|
||||
if (this.debugMode) {
|
||||
this._updateDragFeedback(dragId, {
|
||||
this._updateDragFeedback(actualDragId, {
|
||||
visible: true,
|
||||
content: `开始拖拽 ${componentType}`,
|
||||
type: 'default',
|
||||
@@ -658,8 +719,10 @@ class DragStateManager {
|
||||
}
|
||||
|
||||
if (this.debugMode) {
|
||||
console.log(`🎯 拖拽开始: ${dragId} (${componentType})`, position);
|
||||
console.log(`🎯 拖拽开始: ${actualDragId} (${componentType})`, position);
|
||||
}
|
||||
|
||||
return actualDragId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,7 +733,10 @@ class DragStateManager {
|
||||
const { dragId, position, targetElement, targetArea } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState || dragState.status !== 'active') return;
|
||||
if (!dragState || dragState.status !== 'active') {
|
||||
console.warn(`⚠️ 未找到活跃的拖拽状态: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新位置
|
||||
dragState.updatePosition(position.x, position.y);
|
||||
@@ -726,7 +792,10 @@ class DragStateManager {
|
||||
const { dragId, finalPosition, dropTarget, success = true } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState) return;
|
||||
if (!dragState) {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 完成拖拽
|
||||
dragState.complete('completed', { success, finalPosition, dropTarget });
|
||||
@@ -743,7 +812,10 @@ class DragStateManager {
|
||||
// 从冲突检测器注销
|
||||
this.conflictDetector.unregisterDrag(dragId);
|
||||
|
||||
// 触发状态变更事件
|
||||
// 清理拖拽目标
|
||||
this.dragTargets.delete(dragId);
|
||||
|
||||
// 触发状态变更事件,包含 dragId
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, {
|
||||
dragId,
|
||||
newStatus: 'completed',
|
||||
@@ -773,7 +845,10 @@ class DragStateManager {
|
||||
const { dragId, reason } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState) return;
|
||||
if (!dragState) {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 取消拖拽
|
||||
dragState.complete('cancelled', { reason });
|
||||
@@ -790,7 +865,10 @@ class DragStateManager {
|
||||
// 从冲突检测器注销
|
||||
this.conflictDetector.unregisterDrag(dragId);
|
||||
|
||||
// 触发状态变更事件
|
||||
// 清理拖拽目标
|
||||
this.dragTargets.delete(dragId);
|
||||
|
||||
// 触发状态变更事件,包含 dragId
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, {
|
||||
dragId,
|
||||
newStatus: 'cancelled',
|
||||
@@ -1024,11 +1102,24 @@ class DragStateManager {
|
||||
* 启动清理调度器
|
||||
*/
|
||||
_startCleanupScheduler() {
|
||||
setInterval(() => {
|
||||
if (this.cleanupScheduler) {
|
||||
return;
|
||||
}
|
||||
this.cleanupScheduler = setInterval(() => {
|
||||
this._cleanupExpiredData();
|
||||
}, 300000); // 每5分钟清理一次
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止清理调度器
|
||||
*/
|
||||
_stopCleanupScheduler() {
|
||||
if (this.cleanupScheduler) {
|
||||
clearInterval(this.cleanupScheduler);
|
||||
this.cleanupScheduler = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理过期数据
|
||||
*/
|
||||
@@ -1663,26 +1754,6 @@ class DragStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁管理器
|
||||
*/
|
||||
destroy() {
|
||||
// 取消所有拖拽
|
||||
this.cancelAllDrags();
|
||||
|
||||
// 清理数据
|
||||
this.activeDrags.clear();
|
||||
this.dragHistory = [];
|
||||
this.dragTargets.clear();
|
||||
|
||||
// 清理冲突检测器
|
||||
this.conflictDetector.activeDrags.clear();
|
||||
this.conflictDetector.conflictHistory = [];
|
||||
|
||||
this.isEnabled = false;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
|
||||
/**
|
||||
* Area拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
@@ -1878,18 +1949,8 @@ class DragStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 延迟创建单例实例
|
||||
let dragStateManager = null;
|
||||
|
||||
/**
|
||||
* 确保单例实例存在
|
||||
*/
|
||||
function ensureDragStateManagerInstance() {
|
||||
if (!dragStateManager) {
|
||||
dragStateManager = new DragStateManager();
|
||||
}
|
||||
return dragStateManager;
|
||||
}
|
||||
// 立即创建单例实例,避免并发初始化问题
|
||||
const dragStateManager = new DragStateManager();
|
||||
|
||||
// 便捷操作函数
|
||||
export const dragStateActions = {
|
||||
@@ -1898,150 +1959,153 @@ export const dragStateActions = {
|
||||
* @param {string} dragId - 拖拽ID
|
||||
* @returns {Object} 拖拽状态
|
||||
*/
|
||||
getDragState: (dragId) => ensureDragStateManagerInstance().getDragState(dragId),
|
||||
getDragState: (dragId) => dragStateManager.getDragState(dragId),
|
||||
|
||||
/**
|
||||
* 获取所有活跃拖拽
|
||||
* @returns {Array} 活跃拖拽列表
|
||||
*/
|
||||
getActiveDrags: () => ensureDragStateManagerInstance().getActiveDrags(),
|
||||
getActiveDrags: () => dragStateManager.getActiveDrags(),
|
||||
|
||||
/**
|
||||
* 获取拖拽历史
|
||||
* @param {number} limit - 限制数量
|
||||
* @returns {Array} 历史记录
|
||||
*/
|
||||
getHistory: (limit = 100) => ensureDragStateManagerInstance().getDragHistory(limit),
|
||||
getHistory: (limit = 100) => dragStateManager.getDragHistory(limit),
|
||||
|
||||
/**
|
||||
* 获取统计信息
|
||||
* @returns {Object} 统计信息
|
||||
*/
|
||||
getStats: () => ensureDragStateManagerInstance().getDragStats(),
|
||||
getStats: () => dragStateManager.getDragStats(),
|
||||
|
||||
/**
|
||||
* 设置调试模式
|
||||
* @param {boolean} enabled - 是否启用
|
||||
*/
|
||||
setDebugMode: (enabled) => ensureDragStateManagerInstance().setDebugMode(enabled),
|
||||
setDebugMode: (enabled) => dragStateManager.setDebugMode(enabled),
|
||||
|
||||
/**
|
||||
* 启用/禁用管理器
|
||||
* @param {boolean} enabled - 是否启用
|
||||
*/
|
||||
setEnabled: (enabled) => ensureDragStateManagerInstance().setEnabled(enabled),
|
||||
setEnabled: (enabled) => dragStateManager.setEnabled(enabled),
|
||||
|
||||
/**
|
||||
* 取消所有拖拽
|
||||
*/
|
||||
cancelAll: () => ensureDragStateManagerInstance().cancelAllDrags(),
|
||||
cancelAll: () => dragStateManager.cancelAllDrags(),
|
||||
|
||||
/**
|
||||
* 面板拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onPanelDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStart(eventData),
|
||||
onPanelDragStart: (eventData) => dragStateManager.onPanelDragStart(eventData),
|
||||
|
||||
/**
|
||||
* 面板拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMove(eventData),
|
||||
onPanelDragMove: (eventData) => dragStateManager.onPanelDragMove(eventData),
|
||||
|
||||
/**
|
||||
* 面板拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEnd(eventData),
|
||||
onPanelDragEnd: (eventData) => dragStateManager.onPanelDragEnd(eventData),
|
||||
|
||||
/**
|
||||
* TabPage拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onPanelDragStartFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragStartFromTabPage(eventData),
|
||||
onPanelDragStartFromTabPage: (eventData) => dragStateManager.onPanelDragStartFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* TabPage拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragMoveFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragMoveFromTabPage(eventData),
|
||||
onPanelDragMoveFromTabPage: (eventData) => dragStateManager.onPanelDragMoveFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* TabPage拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragEndFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragEndFromTabPage(eventData),
|
||||
onPanelDragEndFromTabPage: (eventData) => dragStateManager.onPanelDragEndFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onAreaDragStart: (eventData) => ensureDragStateManagerInstance().onAreaDragStart(eventData),
|
||||
onAreaDragStart: (eventData) => dragStateManager.onAreaDragStart(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onAreaDragMove: (eventData) => ensureDragStateManagerInstance().onAreaDragMove(eventData),
|
||||
onAreaDragMove: (eventData) => dragStateManager.onAreaDragMove(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onAreaDragEnd: (eventData) => ensureDragStateManagerInstance().onAreaDragEnd(eventData),
|
||||
onAreaDragEnd: (eventData) => dragStateManager.onAreaDragEnd(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onTabDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStartFromTabPage(eventData),
|
||||
onTabDragStart: (eventData) => dragStateManager.onPanelDragStartFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onTabDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMoveFromTabPage(eventData),
|
||||
onTabDragMove: (eventData) => dragStateManager.onPanelDragMoveFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onTabDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEndFromTabPage(eventData),
|
||||
onTabDragEnd: (eventData) => dragStateManager.onPanelDragEndFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* 初始化拖拽管理器
|
||||
*/
|
||||
initialize: () => ensureDragStateManagerInstance(),
|
||||
initialize: () => dragStateManager,
|
||||
|
||||
/**
|
||||
* 销毁拖拽管理器
|
||||
*/
|
||||
destroy: () => {
|
||||
if (dragStateManager) {
|
||||
// 清理拖拽管理器资源
|
||||
dragStateManager.activeDrags.clear();
|
||||
dragStateManager.dragHistory = [];
|
||||
// 清理拖拽管理器资源,先调用实例的destroy方法清理监听器
|
||||
try {
|
||||
dragStateManager.destroy();
|
||||
} catch (e) {
|
||||
console.warn('销毁拖拽状态管理器时出错:', e);
|
||||
}
|
||||
dragStateManager = null;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁,所有资源已清理');
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 导出
|
||||
export default {
|
||||
getInstance: ensureDragStateManagerInstance,
|
||||
getInstance: () => dragStateManager,
|
||||
actions: dragStateActions
|
||||
};
|
||||
export { DragState };
|
||||
Reference in New Issue
Block a user