From f0e0b7915e112125a7e1a8ac9b76f3666b49ecf8 Mon Sep 17 00:00:00 2001 From: tianyongbao Date: Fri, 9 Jan 2026 20:14:24 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20bug=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ManagePage.vue | 166 +++++++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 59 deletions(-) diff --git a/src/views/ManagePage.vue b/src/views/ManagePage.vue index 399f413..ccd3ae5 100644 --- a/src/views/ManagePage.vue +++ b/src/views/ManagePage.vue @@ -448,13 +448,13 @@ export default { if (this.timer) { clearInterval(this.timer) } + // 清理所有Sortable实例 + this.destroySortables() }, updated() { - // 数据更新后重新初始化拖拽 - this.$nextTick(() => { - this.initSortable() - }) + // 移除自动重新初始化,避免频繁销毁重建导致事件监听器错误 + // 只在必要时(如数据加载完成)手动调用 initSortable() }, methods: { @@ -639,9 +639,11 @@ export default { // 切换Tab switchTab(superCategoryId) { this.activeSuperCategoryId = superCategoryId - // 切换Tab后重新调整padding + // 切换Tab后重新调整padding和重新初始化拖拽 this.$nextTick(() => { this.adjustContainerPadding() + // 切换Tab时需要重新初始化拖拽(因为DOM结构变化了) + this.initSortable() }) }, @@ -703,9 +705,11 @@ export default { this.activeSuperCategoryId = superCategories[0].id } - // 数据加载完成后调整padding + // 数据加载完成后调整padding和初始化拖拽 this.$nextTick(() => { this.adjustContainerPadding() + // 只在数据加载完成时初始化拖拽,而非每次updated + this.initSortable() }) } } catch (error) { @@ -1155,64 +1159,108 @@ export default { } }, + // 销毁所有Sortable实例 + destroySortables() { + // 使用更安全的销毁方式,避免removeEventListener报错 + if (this.superCategorySortable) { + try { + this.superCategorySortable.destroy() + } catch (e) { + // 忽略销毁时的错误 + } + this.superCategorySortable = null + } + + if (this.categorySortable) { + try { + this.categorySortable.destroy() + } catch (e) { + // 忽略销毁时的错误 + } + this.categorySortable = null + } + + if (this.toolSortables && this.toolSortables.length > 0) { + this.toolSortables.forEach(s => { + if (s) { + try { + s.destroy() + } catch (e) { + // 忽略销毁时的错误 + } + } + }) + this.toolSortables = [] + } + }, + // 初始化拖拽排序 initSortable() { - // 销毁旧的 Sortable 实例 - if (this.superCategorySortable) { - this.superCategorySortable.destroy() - } - if (this.categorySortable) { - this.categorySortable.destroy() - } - if (this.toolSortables) { - this.toolSortables.forEach(s => s.destroy()) - } - this.toolSortables = [] + // 先销毁旧的 Sortable 实例 + this.destroySortables() - // 大分类 Tab 拖拽 - const tabListEl = document.querySelector('.tab-list') - if (tabListEl) { - this.superCategorySortable = Sortable.create(tabListEl, { - animation: 150, - handle: '.tab-item', - ghostClass: 'sortable-ghost', - chosenClass: 'sortable-chosen', - dragClass: 'sortable-drag', - onEnd: (evt) => { - this.handleSuperCategorySort(evt) + // 延迟初始化,确保DOM已完全更新 + this.$nextTick(() => { + // 大分类 Tab 拖拽 + const tabListEl = document.querySelector('.tab-list') + if (tabListEl && !this.superCategorySortable) { + try { + this.superCategorySortable = Sortable.create(tabListEl, { + animation: 150, + handle: '.tab-item', + ghostClass: 'sortable-ghost', + chosenClass: 'sortable-chosen', + dragClass: 'sortable-drag', + forceFallback: true, // 使用fallback模式,避免原生拖拽事件冲突 + onEnd: (evt) => { + this.handleSuperCategorySort(evt) + } + }) + } catch (e) { + console.warn('初始化大分类拖拽失败:', e) + } + } + + // 书签分组拖拽 + const categoryListEl = document.querySelector('.category-list') + if (categoryListEl && !this.categorySortable) { + try { + this.categorySortable = Sortable.create(categoryListEl, { + animation: 150, + handle: '.category-item', + ghostClass: 'sortable-ghost', + chosenClass: 'sortable-chosen', + dragClass: 'sortable-drag', + forceFallback: true, + onEnd: (evt) => { + this.handleCategorySort(evt) + } + }) + } catch (e) { + console.warn('初始化分组拖拽失败:', e) + } + } + + // 网址列表拖拽(每个分组都需要初始化) + const toolLists = document.querySelectorAll('.tool-list') + toolLists.forEach((toolListEl, index) => { + try { + const sortable = Sortable.create(toolListEl, { + animation: 150, + handle: '.tool-drag-handle', // 只能通过拖拽手柄区域拖动 + ghostClass: 'sortable-ghost', + chosenClass: 'sortable-chosen', + dragClass: 'sortable-drag', + forceFallback: true, + onEnd: (evt) => { + this.handleToolSort(evt, index) + } + }) + this.toolSortables.push(sortable) + } catch (e) { + console.warn('初始化网址拖拽失败:', e) } }) - } - - // 书签分组拖拽 - const categoryListEl = document.querySelector('.category-list') - if (categoryListEl) { - this.categorySortable = Sortable.create(categoryListEl, { - animation: 150, - handle: '.category-item', - ghostClass: 'sortable-ghost', - chosenClass: 'sortable-chosen', - dragClass: 'sortable-drag', - onEnd: (evt) => { - this.handleCategorySort(evt) - } - }) - } - - // 网址列表拖拽(每个分组都需要初始化) - const toolLists = document.querySelectorAll('.tool-list') - toolLists.forEach((toolListEl, index) => { - const sortable = Sortable.create(toolListEl, { - animation: 150, - handle: '.tool-drag-handle', // 只能通过拖拽手柄区域拖动 - ghostClass: 'sortable-ghost', - chosenClass: 'sortable-chosen', - dragClass: 'sortable-drag', - onEnd: (evt) => { - this.handleToolSort(evt, index) - } - }) - this.toolSortables.push(sortable) }) },