发布于 2026-01-06 7 阅读
0

使用 React 创建 Chrome 扩展程序 DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

使用 React 创建 Chrome 扩展程序

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

最近,我着手开发一个 Chrome 扩展程序,并利用 JavaScript 和 React 将一个组件注入到网站中。最终成果完美地结合了 Mutation Observer 和 JavaScript 的强大功能!

代码可以在Github上找到。

准备!

首先,我从Chrome 开发者网站下载了一个 Chrome 扩展程序的入门模板。如果你想学习扩展程序开发的基础知识,我强烈建议你访问这个网站。我立即删除了 `<filename>` options.jsoptions.html`<filename>` 和popup.js`<filename>` 文件。在 `<filename>`manifest.json文件中,我删除了数组中的options_page键和值。接下来,你需要向数组中添加内容storagepermissionshttps://www.myweekinjs.com/permissions

我会在文中多次提到myweekinjs ,它可以是任何你想注入 React 组件的网站。

接下来,我创建了一个app.js简单的console.log测试用例来验证脚本是否有效,并更新了脚本background.js

chrome.runtime.onInstalled.addListener(function() {
  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
    chrome.declarativeContent.onPageChanged.addRules([{
      conditions: [new chrome.declarativeContent.PageStateMatcher({
        pageUrl: {
          hostEquals: 'www.myweekinjs.com',
          schemes: ['https', 'http'],
          pathContains: 'inject-me'
        },
        css: ['div']
      })],
      actions: [
        new chrome.declarativeContent.RequestContentScript({
          js: ['app.js']
        })
      ]
    }]);
  });
});
Enter fullscreen mode Exit fullscreen mode

好了!信息量真大!background.js脚本将执行以下操作:

  1. 注意页面/标签页的变化
  2. 检查当前页面是否为 (http|https): //www.myweekinjs.com/inject-me
  3. 如果是,它将加载我们的app.js文件

请按照以下步骤加载您的扩展程序以进行测试。

让我们开始编写脚本吧!

下一步是创建webpack.config.js用于编译 React 和 Javascript 的文件。此时,我建议创建一个名为 dist 的文件夹,其中包含当前文件(不包括 node_modules app.js),并将该文件夹解压为扩展名。这样,您就可以将代码编译到这个dist文件夹中,而不会将node_modules包含到扩展名中。

我们将使用这个很棒的资源来生成我们的 webpack 和 .babelrc 文件createapp.dev

  1. 打开资源 ^
  2. 勾选 React 和 Babel。取消勾选 React 热加载器
  3. 运行npm init -y并安装资源中列出的软件包。
  4. webpack.config.js将文件复制.babelrc到您的项目中
  5. scripts从……复制package.json

我们需要做一些小的调整,包括webpack.config.js更改输入和输出设置;

var config = {
  entry: './app.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.js'
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

build-dev脚本更改为:

"dev": "webpack -d --mode development --watch"
Enter fullscreen mode Exit fullscreen mode

你的语法可能存在一些问题.babelrc,不过应该很容易解决,主要是双引号的使用问题。

运行build-prod脚本后,文件将被编译app.js。解压并重新加载后,你应该会看到和console.log之前一样的内容。虽然过程漫长,但接下来才是真正有趣的部分!

让我们一起快乐起来!

我们希望我们的应用程序能够实现以下几个功能;

  1. 请等待页面完全加载。
  2. 观察目标容器上的突变
  3. 插入我们的 React 根目录
  4. 渲染 React 组件

我们将从以下结构开始。它为窗口添加了一个监听器load,并包含我们的主要回调函数,我将其命名为app

window.addEventListener('load', function() {})

const app = () => {}
Enter fullscreen mode Exit fullscreen mode

第一步完成!继续!

接下来,我们将添加一个Mutation Observer,它赋予我们监视 DOM 树变化的强大功能。这非常实用。在我们的项目中,我们将监视测试页面target-test上的 div 元素(测试页面位于我的个人博客上)。以下代码已添加到加载回调函数中。

// Specifies the element we want to watch
const watch = document.getElementById('target-test')

// Creates a new Mutation Observer
const observer = new MutationObserver((mutationList, observer) => {

})

// Starts observing the child list of the element
observer.observe(watch, {
  childList: true
})
Enter fullscreen mode Exit fullscreen mode

接下来,我们要遍历这些变更,如果能找到我们要查找的元素,就调用我们的应用程序方法。

const observer = new MutationObserver((mutationList, observer) => {
  // Loops through the mutations
  for (const mutation of mutationList) {
    // Checks if it is a change to the child elements
    if (mutation.type === 'childList') {
      // Attempts to find the p tag
      const target = watch.querySelector('p')
      if (target) {
        // Calls our app method
        app(observer, target)
      }
    }
  }
})

// Update the callback to accept those arguements
const app = (observer, target) => {}
Enter fullscreen mode Exit fullscreen mode

快完成了!现在我们要为 React 组件创建一个根元素,并将其插入到目标元素之前。

const app = (observer, target) => {
  // Disconnects from the observer to stop any additional watching
  observer.disconnect()

  // Checks if the element doesn't exist
  if (!document.getElementById('react-root-test')) {
    // Create and inserts the element before the target
    const parent = target.parentNode
    const root = document.createElement('div')
    root.setAttribute('id', 'react-root-test')

    parent.insertBefore(root, target)
  }
}
Enter fullscreen mode Exit fullscreen mode

让我们开始反应吧!

现在我们有了 React 根组件,终于可以创建并渲染组件了。我将在同一个文件中创建一个简单的 React 组件。当然,你可以创建任何你想要的组件,这完全取决于你!添加组件后,解压扩展程序并重新加载测试页面,你应该就能看到组件出现了!

import React from 'react'
import ReactDOM from 'react-dom'

const TestComponent = () => (
  <h1>I am dynamically added!</h1>
)

const app = () => {
  //...
  parent.insertBefore(root, target)

  ReactDOM.render(<TestComponent />, document.getElementById('react-root-test'))
}
Enter fullscreen mode Exit fullscreen mode

繁荣!

我们成功了!这仅仅是使用 Chrome 扩展程序和 React 实现功能的冰山一角。运用同样的技术,你还可以为网站添加各种功能,类似于 Grammarly 或 LastPass 等扩展程序。可能性几乎是无限的!

总结

我觉得这个项目挺酷的。我之前完全没想到用 Chrome 扩展程序能做到这种程度。在这个例子里用 Mutation Observer 可能有点小题大做。不过,当你遇到一个动态渲染内容的网站时,能够等到需要的内容加载完毕再执行操作,真的非常棒!如果你对代码或流程有任何疑问,欢迎在Twitter上联系我,我很乐意继续讨论并改进我的代码。


感谢您阅读我的文章,这对我意义重大!❤️ 欢迎提供任何反馈或评论,我一直在努力改进,也期待与您进行有意义的讨论。这篇文章是我参加#myweekinjs挑战的一部分,如果您有兴趣了解更多,我还有其他有趣的文章。

👋 下次再见!

文章来源:https://dev.to/hurricaneinteractive/creating-a-chrome-extension-with-react-2bnm