我想单击一个按钮以注入脚本以使用chrome.tabs.executeScript
来获取一些DOM项目。由于某种原因,它仅在初始页面加载时起作用一次,但是如果再次单击该按钮,则chrome.tabs.executeScript
返回[null]
。这是我的代码,感兴趣的函数是handleClick
:
import React, { useEffect, useState } from 'react';
import { Button, Paper } from '@material-ui/core';
// import { makeStyles } from '@material-ui/core/styles';
import * as chromeAsync from 'chrome-extension-async';
function getFnBody(fn) {
const fnStr = fn.toString();
return fnStr.substring(fnStr.indexOf('{') + 1, fnStr.lastIndexOf('}'));
}
async function clearLinks({ key = 'default' } = {}) {
// eslint-disable-next-line
await chrome.storage.local.set({ [key]: {} });
}
async function getLinks({ key = 'default' } = {}) {
// eslint-disable-next-line
return (await chrome.storage.local.get([key]))[key];
}
async function appendLinks({ key = 'default', links } = {}) {
// eslint-disable-next-line
const data = await chrome.storage.local.get([key]);
const allLinks = data[key] || {};
links.map((l) => {
const date = allLinks[l];
if (!date) {
allLinks[l] = Date.now();
}
});
// eslint-disable-next-line
await chrome.storage.local.set({ [key]: allLinks });
}
async function handleClick() {
// eslint-disable-next-line
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
const activeTab = tabs[0];
// eslint-disable-next-line
const results = await chrome.tabs.executeScript(activeTab.id, {
code: getFnBody(getLinkedInHrefs),
});
const hrefs = JSON.parse(results);
await appendLinks({ links: hrefs });
// eslint-disable-next-line
await chrome.tabs.executeScript(activeTab.id, {
code: getFnBody(clickNext),
});
}
// Chrome Injected
function getLinkedInHrefs() {
// window.location.toString();
const hrefList = [];
const list = document.querySelectorAll(
'.search-result__info a.search-result__result-link',
);
list.forEach((node) => {
hrefList.push(node.href);
});
JSON.stringify(hrefList);
}
function clickNext() {
document.querySelector('.artdeco-pagination__button--next').click();
}
function Home() {
const [state, setState] = useState({});
useEffect(() => {
async function init() {
const links = await getLinks();
}
init();
});
return (
<div>
<Paper className="home-page">
<Button onClick={handleClick}>
Let's Fucking GO
</Button>
</Paper>
</div>
);
}
export default Home;
我不确定发生了什么,但是我有另一个更旧的(第15号反应)版本正在运行,但是在使用create-react-app
搭建了一个新应用后,它仅在第一次重新加载时起作用。
getFnBody
会提取函数的内容,因此const
声明会污染内容脚本上下文的全局范围(“隔离的世界”),这会阻止代码再次运行,因为const
或let
变量只能在范围中声明一次。
最简单的解决方案是删除getFnBody
,然后将代码包装在IIFE中:
const results = await chrome.tabs.executeScript(activeTab.id, {
code: `(${getLinkedInHrefs})()`,
});
当然,您需要在这些注入的函数中使用return
:
function getLinkedInHrefs() {
//.........................
return JSON.stringify(hrefList);
}