滚动上的活动选项卡元素在 React chrome 扩展中不起作用。 下面是我的代码,用于检测滚动时活动选项卡的文档元素。但它没有按预期工作。
我希望在滚动发生时安慰“滚动到结束”(当滚动结束时......即使发生小滚动)。
滚动上的活动选项卡元素在 React chrome 扩展中不起作用。 下面是我的代码,用于检测滚动时活动选项卡的文档元素。但它没有按预期工作。 应用程序.tsx
import React, { useEffect } from 'react';
import './App.css';
import { useRecoilState } from 'recoil';
import messagesState from './states/messages';
function App() {
const [htmlContent, setHtmlContent] = useRecoilState<any>(messagesState);
useEffect(() => {
const handleMessage = (event: any) => {
if (event.data && event.data.type === 'scrollEnd') {
console.log('Scrolled to end');
}
};
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
};
}, []);
return (
<div className="App">
</div>
);
}
export default App;
背景.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'scrollEnd') {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const activeTab = tabs[0];
chrome.scripting.executeScript({
target: { tabId: activeTab.id },
func: () => {
window.postMessage({ type: 'scrollEnd' }, '*');
},
});
});
}
});
contentScript.js
let scrollTimeout;
const targetDiv = document.querySelector('.c-scrollbar__hider');
function sendScrollEndMessage() {
chrome.runtime.sendMessage({ type: 'scrollEnd' });
}
targetDiv.addEventListener('scroll', () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(sendScrollEndMessage, 300);
});
manifest.json
{
"manifest_version": 3,
"name": "ASDF",
"version": "1.0",
"description": "ASDF",
"host_permissions": ["<all_urls>"],
"icons": {
"16": "images/slack-logo.png",
"32": "images/slack-logo.png",
"180": "images/slack-logo.png",
"192": "images/slack-logo.png",
"512": "images/slack-logo.png"
},
"offline_enabled": true,
"permissions": ["storage", "activeTab", "contextMenus", "tabs", "scripting"],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"]
}
],
"action": {
"default_popup": "index.html"
}
}
我希望在滚动发生时安慰“滚动到结束”(当滚动结束时......即使发生小滚动)。
window.postMessage 在这里不起作用,因为弹出窗口是一个不同的窗口,与选项卡无关。
chrome
消息传递。
删除
content_scripts
并使用编程注入来代替仅在显示弹出窗口时使用的内容,因为此声明不必要地在每个选项卡中运行内容脚本,浪费 CPU 和内存。
从manifest.json和后台脚本中删除
background
,你不需要它。
不需要在useEffect中取消注册监听器,因为当弹出窗口关闭时,整个JS环境都被破坏了。
useEffect(() => {
const handleMessage = msg => {
console.log(msg);
// right-click inside the popup and select "inspect" in the menu to see the console
};
chrome.windows.getCurrent(async wnd => {
const [tab] = await chrome.tabs.query({active: true, windowId: wnd.id});
chrome.runtime.onConnect.addListener(port => {
if (port.sender.tab?.id === tab.id) {
port.onMessage.addListener(handleMessage);
}
});
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['contentScript.js'],
});
});
}, []);
// contentScript.js
if (window.ACTIVE !== 1) {
window.ACTIVE = 1;
let scrollTimeout;
const port = chrome.runtime.connect({name: 'scroll'});
const el = document.querySelector('.c-scrollbar__hider');
el.addEventListener('scroll', onscroll);
port.onDisconnect.addListener(shutdown);
function shutdown() {
el.removeEventListener('scroll', onscroll);
delete window.ACTIVE;
}
function sendScrollEndMessage() {
if (!chrome.runtime.id) return shutdown(); // extension was reloaded
port.postMessage({ type: 'scrollEnd' });
}
function onscroll() {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(sendScrollEndMessage, 300);
}
}