反应Chrome扩展程序-chrome.tabs.executeScript`不一致

问题描述 投票:0回答:1

我想单击一个按钮以注入脚本以使用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搭建了一个新应用后,它仅在第一次重新加载时起作用。

javascript reactjs google-chrome google-chrome-extension react-hooks
1个回答
0
投票
代码中的

getFnBody会提取函数的内容,因此const声明会污染内容脚本上下文的全局范围(“隔离的世界”),这会阻止代码再次运行,因为constlet变量只能在范围中声明一次。

最简单的解决方案是删除getFnBody,然后将代码包装在IIFE中:

const results = await chrome.tabs.executeScript(activeTab.id, {
  code: `(${getLinkedInHrefs})()`,
});

当然,您需要在这些注入的函数中使用return

function getLinkedInHrefs() {
  //.........................
  return JSON.stringify(hrefList);
}
© www.soinside.com 2019 - 2024. All rights reserved.