如何让chrome.scripting.executeScript重复执行同一脚本文件?
Chrome扩展executeScript后续点击无效的解决方法及代码复用方案
Chrome的scripting.executeScript有个特性:同一个标签页内,同一个脚本文件只会被注入并执行一次。你之前的代码里,toggleExtension.ts的顶层代码(最后一行的togglePanel调用)只在首次注入时运行,后续点击图标虽然executeScript返回成功,但脚本已经存在于页面环境中,不会重复执行顶层逻辑,所以没有效果。
方案一:用func参数传递配置(推荐,复用性强)
把侧边栏的开关逻辑封装成函数,在background里通过func参数直接执行,同时传入目标HTML路径和挂载ID,这样每次点击都会触发逻辑,还能轻松适配不同的HTML文件。
修改后的background代码:
chrome.action.onClicked.addListener(() => { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { const tabId = tabs[0].id!; // 封装核心开关逻辑 const togglePanel = (mountId: string, htmlPath: string) => { const createIframe = (pageUrl: string, id: string) => { const iframeEl = document.createElement('iframe'); iframeEl.id = id; iframeEl.setAttribute( 'style', ` z-index: 9999999999; position: fixed; height: 100%; width: 100%; top: 0; right: 0; bottom: 0; left: 0; border: 0; ` ); iframeEl.src = chrome.runtime.getURL(pageUrl); iframeEl.allow = 'clipboard-write'; return iframeEl; }; const dialog = document.getElementById(mountId); dialog ? dialog.remove() : document.body.appendChild(createIframe(htmlPath, mountId)); }; // 执行逻辑,传入自定义配置 chrome.scripting.executeScript({ target: { tabId }, func: togglePanel, args: ['extension-sidebar-id', 'pages/sidebar.html'], // 替换这里的参数即可适配其他HTML }); }); });
这种方式不需要单独的toggleExtension.ts文件,所有逻辑直接在background里封装,修改args数组就能切换不同的侧边栏页面,复用性拉满。
方案二:保留脚本文件,通过全局函数触发
如果你的开关逻辑比较复杂,不想全部写在background里,可以把togglePanel暴露为全局函数,注入脚本后通过调用全局函数触发逻辑:
修改toggleExtension.ts:
const createIframe = (pageUrl: string, id: string) => { const iframeEl = document.createElement('iframe') iframeEl.id = id iframeEl.setAttribute( 'style', ` z-index: 9999999999; position: fixed; height: 100%; width: 100%; top: 0px; right: 0px; bottom: 0px; left: 0px; border: 0; ` ) iframeEl.src = chrome.runtime.getURL(pageUrl) iframeEl.allow = 'clipboard-write' return iframeEl } export const togglePanel = (mountId: string, htmlPath: string) => { const dialog = document.getElementById(mountId) if (dialog) { dialog.parentElement?.removeChild(dialog) } else { const iframeEl = createIframe(htmlPath, mountId) document.body.appendChild(iframeEl) } } // 暴露到全局window对象 ;(window as any).extensionTogglePanel = togglePanel
修改后的background代码:
import toggleExtension from './toggleExtension.ts?script' chrome.action.onClicked.addListener(async () => { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); const tabId = tabs[0].id!; // 首次注入脚本,后续注入会跳过执行顶层代码,但脚本已存在 await chrome.scripting.executeScript({ target: { tabId }, files: [toggleExtension], }); // 调用全局函数执行开关逻辑 await chrome.scripting.executeScript({ target: { tabId }, func: (mountId, htmlPath) => { (window as any).extensionTogglePanel(mountId, htmlPath); }, args: ['extension-sidebar-id', 'pages/sidebar.html'], // 同样可替换参数适配其他HTML }); });
内容的提问来源于stack exchange,提问作者Pietro Coelho
相关产品推荐
相关产品推荐

