refactor: 统一 webTab 事件分发逻辑

新增 dispatchToTabBar() 函数,封装 window 模式检查逻辑:
  - window 模式无标签栏,跳过 executeJavaScript 调用
  - 避免 did-stop-loading 监听器累积导致 MaxListenersExceededWarning
  - 统一 14 处调用点,提升代码一致性和可维护性
This commit is contained in:
kuaifan 2026-01-14 13:41:28 +08:00
parent c0183e62fb
commit 792989a504

View File

@ -235,20 +235,30 @@ function recreatePreloadPool() {
} }
} }
/**
* 向标签栏分发事件 tab 模式有效window 模式无标签栏
* @param {object} wd - windowData 对象
* @param {object} data - 事件数据
*/
function dispatchToTabBar(wd, data) {
if (!wd || !wd.window || wd.mode === 'window') {
return Promise.resolve()
}
return utils.onDispatchEvent(wd.window.webContents, data)
}
/** /**
* 内置浏览器 - 延迟发送导航状态 * 内置浏览器 - 延迟发送导航状态
*/ */
function notifyNavigationState(item) { function notifyNavigationState(item) {
setTimeout(() => { setTimeout(() => {
const wd = webTabWindows.get(item.view.webTabWindowId) const wd = webTabWindows.get(item.view.webTabWindowId)
if (wd && wd.window) { dispatchToTabBar(wd, {
utils.onDispatchEvent(wd.window.webContents, {
event: 'navigation-state', event: 'navigation-state',
id: item.id, id: item.id,
canGoBack: item.view.webContents.navigationHistory.canGoBack(), canGoBack: item.view.webContents.navigationHistory.canGoBack(),
canGoForward: item.view.webContents.navigationHistory.canGoForward() canGoForward: item.view.webContents.navigationHistory.canGoForward()
}).then(_ => { }) })
}
}, 100) }, 100)
} }
@ -517,15 +527,17 @@ function createWebTabWindowInstance(windowId, position, mode = 'tab') {
}) })
webTabWindow.on('enter-full-screen', () => { webTabWindow.on('enter-full-screen', () => {
utils.onDispatchEvent(webTabWindow.webContents, { const wd = webTabWindows.get(windowId)
dispatchToTabBar(wd, {
event: 'enter-full-screen', event: 'enter-full-screen',
}).then(_ => { }) })
}) })
webTabWindow.on('leave-full-screen', () => { webTabWindow.on('leave-full-screen', () => {
utils.onDispatchEvent(webTabWindow.webContents, { const wd = webTabWindows.get(windowId)
dispatchToTabBar(wd, {
event: 'leave-full-screen', event: 'leave-full-screen',
}).then(_ => { }) })
}) })
webTabWindow.on('close', event => { webTabWindow.on('close', event => {
@ -775,12 +787,12 @@ function createWebTabView(windowId, args) {
const currentWindowId = browserView.webTabWindowId const currentWindowId = browserView.webTabWindowId
const wd = webTabWindows.get(currentWindowId) const wd = webTabWindows.get(currentWindowId)
if (!wd || !wd.window) return if (!wd || !wd.window) return
utils.onDispatchEvent(wd.window.webContents, { dispatchToTabBar(wd, {
event: 'title', event: 'title',
id: browserView.webContents.id, id: browserView.webContents.id,
title: errorDescription, title: errorDescription,
url: browserView.webContents.getURL(), url: browserView.webContents.getURL(),
}).then(_ => { }) })
}) })
browserView.webContents.on('page-favicon-updated', async (_, favicons) => { browserView.webContents.on('page-favicon-updated', async (_, favicons) => {
// 使用动态窗口ID支持标签在窗口间转移 // 使用动态窗口ID支持标签在窗口间转移
@ -802,23 +814,21 @@ function createWebTabView(windowId, args) {
} }
// 发送验证后的 favicon 给前端 // 发送验证后的 favicon 给前端
utils.onDispatchEvent(wd.window.webContents, { dispatchToTabBar(wd, {
event: 'favicon', event: 'favicon',
id: tabId, id: tabId,
favicon: base64Favicon || '' favicon: base64Favicon || ''
}).then(_ => { }) })
}) })
// 页面加载状态管理忽略SPA路由切换(isSameDocument) // 页面加载状态管理忽略SPA路由切换(isSameDocument)
browserView._loadingActive = false browserView._loadingActive = false
browserView._loadingChecker = null browserView._loadingChecker = null
const dispatchLoading = (event) => { const dispatchLoading = (event) => {
const wd = webTabWindows.get(browserView.webTabWindowId) const wd = webTabWindows.get(browserView.webTabWindowId)
if (wd && wd.window) { dispatchToTabBar(wd, {
utils.onDispatchEvent(wd.window.webContents, {
event, event,
id: browserView.webContents.id, id: browserView.webContents.id,
}).then(_ => { }) })
}
} }
const startLoading = () => { const startLoading = () => {
if (browserView._loadingActive) return if (browserView._loadingActive) return
@ -1037,10 +1047,10 @@ function activateWebTabInWindow(windowId, id) {
}) })
resizeWebTabInWindow(windowId, item.id) resizeWebTabInWindow(windowId, item.id)
item.view.webContents.focus() item.view.webContents.focus()
utils.onDispatchEvent(webTabWindow.webContents, { dispatchToTabBar(windowData, {
event: 'switch', event: 'switch',
id: item.id, id: item.id,
}).then(_ => { }) })
} }
/** /**
@ -1092,10 +1102,10 @@ function closeWebTabInWindow(windowId, id) {
webTabView.splice(index, 1) webTabView.splice(index, 1)
} }
utils.onDispatchEvent(webTabWindow.webContents, { dispatchToTabBar(windowData, {
event: 'close', event: 'close',
id: item.id, id: item.id,
}).then(_ => { }) })
if (webTabView.length === 0) { if (webTabView.length === 0) {
userConf?.set('webTabWindow', webTabWindow.getBounds()) userConf?.set('webTabWindow', webTabWindow.getBounds())
@ -1158,10 +1168,10 @@ function detachWebTab(windowId, tabId, screenX, screenY) {
sourceWindowData.views.splice(tabIndex, 1) sourceWindowData.views.splice(tabIndex, 1)
// 通知源窗口标签已关闭 // 通知源窗口标签已关闭
utils.onDispatchEvent(sourceWindow.webContents, { dispatchToTabBar(sourceWindowData, {
event: 'close', event: 'close',
id: tabId, id: tabId,
}).then(_ => { }) })
// 创建新窗口,使用源窗口的尺寸 // 创建新窗口,使用源窗口的尺寸
const sourceBounds = sourceWindow.getBounds() const sourceBounds = sourceWindow.getBounds()
@ -1225,7 +1235,7 @@ function detachWebTab(windowId, tabId, screenX, screenY) {
// 通知新窗口创建标签(传递完整状态信息) // 通知新窗口创建标签(传递完整状态信息)
newWindow.webContents.once('dom-ready', () => { newWindow.webContents.once('dom-ready', () => {
const isLoading = view.webContents.isLoading() const isLoading = view.webContents.isLoading()
utils.onDispatchEvent(newWindow.webContents, { dispatchToTabBar(newWindowData, {
event: 'create', event: 'create',
id: tabId, id: tabId,
url: view.webContents.getURL(), url: view.webContents.getURL(),
@ -1233,11 +1243,11 @@ function detachWebTab(windowId, tabId, screenX, screenY) {
title: view.webContents.getTitle(), title: view.webContents.getTitle(),
state: isLoading ? 'loading' : 'loaded', state: isLoading ? 'loading' : 'loaded',
favicon, favicon,
}).then(_ => { }) })
utils.onDispatchEvent(newWindow.webContents, { dispatchToTabBar(newWindowData, {
event: 'switch', event: 'switch',
id: tabId, id: tabId,
}).then(_ => { }) })
}) })
// 处理源窗口 // 处理源窗口
@ -1284,10 +1294,10 @@ function attachWebTab(sourceWindowId, tabId, targetWindowId, insertIndex) {
sourceWindowData.views.splice(tabIndex, 1) sourceWindowData.views.splice(tabIndex, 1)
// 通知源窗口标签已关闭 // 通知源窗口标签已关闭
utils.onDispatchEvent(sourceWindow.webContents, { dispatchToTabBar(sourceWindowData, {
event: 'close', event: 'close',
id: tabId, id: tabId,
}).then(_ => { }) })
// 更新视图所属窗口 // 更新视图所属窗口
view.webTabWindowId = targetWindowId view.webTabWindowId = targetWindowId
@ -1324,7 +1334,7 @@ function attachWebTab(sourceWindowId, tabId, targetWindowId, insertIndex) {
// 通知目标窗口创建标签(传递完整状态信息) // 通知目标窗口创建标签(传递完整状态信息)
const isLoading = view.webContents.isLoading() const isLoading = view.webContents.isLoading()
utils.onDispatchEvent(targetWindow.webContents, { dispatchToTabBar(targetWindowData, {
event: 'create', event: 'create',
id: tabId, id: tabId,
url: view.webContents.getURL(), url: view.webContents.getURL(),
@ -1333,7 +1343,7 @@ function attachWebTab(sourceWindowId, tabId, targetWindowId, insertIndex) {
insertIndex: actualInsertIndex, insertIndex: actualInsertIndex,
state: isLoading ? 'loading' : 'loaded', state: isLoading ? 'loading' : 'loaded',
favicon, favicon,
}).then(_ => { }) })
// 激活新添加的标签 // 激活新添加的标签
activateWebTabInWindow(targetWindowId, tabId) activateWebTabInWindow(targetWindowId, tabId)
@ -1848,14 +1858,12 @@ function registerIPC() {
const canGoForward = item.view.webContents.navigationHistory.canGoForward() const canGoForward = item.view.webContents.navigationHistory.canGoForward()
const wd = webTabWindows.get(item.view.webTabWindowId) const wd = webTabWindows.get(item.view.webTabWindowId)
if (wd && wd.window) { dispatchToTabBar(wd, {
utils.onDispatchEvent(wd.window.webContents, {
event: 'navigation-state', event: 'navigation-state',
id: item.id, id: item.id,
canGoBack, canGoBack,
canGoForward canGoForward
}).then(_ => { }) })
}
event.returnValue = "ok" event.returnValue = "ok"
}) })