如何在不使用 iframe 的情况下使用 Angular 为 chromeextension 创建侧边栏

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

我正在使用 Angular 开发 chrome 扩展,我的扩展与 MaxAI chrome 扩展类似,当用户单击小部件时,它会打开侧边栏。

我尝试了一些教程来创建侧边栏,但侧边栏包含 iframe。不使用 iframe 是否可以创建类似这样的侧边栏

我检查了 MaxAI 侧边栏,我可以看到他们没有使用 iframe,而是我可以看到 DOM 中添加了一些特殊标签,如下所示

use-chat-gpt-ai

这是我使用 iframe 的实现

function injectAngularApplication() {
  var angularApplicationIframe = document.createElement('iframe');
  angularApplicationIframe.src = chrome.runtime.getURL('index.html');
  angularApplicationIframe.id = 'angularApplication';
  angularApplicationIframe.allow = 'clipboard-read; clipboard-write';
  angularApplicationIframe.className = 'angular_application_iframe';

  document.body.appendChild(angularApplicationIframe);
}

它将我的 Angular 应用程序注入到 iframe 中。我不想使用 iframe 的原因是当我们重新加载框架时它显示为空,即使我添加了哈希路由。

清单.json

{
  "name": "angularchrome",
  "description": "AngularChrome Extension.",
  "version": "1.0.1",
  "manifest_version": 3,
  "permissions": [
    "webNavigation"
  ],
  "action": {
    "default_icon": "/assets/icons/Icon.png",
    "default_title": "Click me!"
  },
  "icons": {
    "16": "/assets/icons/Icon.png",
    "32": "/assets/icons/Icon.png",
    "48": "/assets/icons/Icon.png",
    "128": "/assets/icons/Icon.png"
  },
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "css": ["content.css"]
    }
  ],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  },
  "web_accessible_resources": [
    {
      "resources": [
        "index.html",
        "toolbar.html",
        "toolbar.scss",
        "toolbar.js",
        "/assets/icons/ICON.png",
        "main.ts"
      ],
      "matches": ["<all_urls>"]
    }
  ]
}

注意:我不想使用chrome提供的侧面板。

任何人都可以建议我一些关于如何使用 Angular 创建 chrome 扩展的更好见解吗?

angular iframe google-chrome-extension
1个回答
0
投票

我做了一个名为 Rafflesia 的开源项目。在其中,我使用 content script 生成 DOM 元素并将它们插入到页面上下文中。

这是我的 content-script.js 的片段:

const scriptsToLoad = ['webpage-script.js'];
scriptsToLoad.forEach(script => {
  const s = document.createElement('script');
  s.src = chrome.runtime.getURL(script);
  (document.head || document.documentElement).appendChild(s);
  s.onload = function () {
    s.remove();
  };
});

const toggler = document.createElement('button')
toggler.innerText = '▲'
toggler.style.position = 'fixed'
// ...
toggler.onclick = toggle
document.body.appendChild(toggler)

const heightAdjuster = document.createElement('div')
heightAdjuster.innerText = '⋯'
heightAdjuster.style.position = 'fixed'
// ...
heightAdjuster.onmousedown = adjustEnter
// ...
document.body.appendChild(heightAdjuster)

这部分都是普通的 JS,因为使用 Angular 创建构建环境并插入到页面中非常困难。您必须 (1) 手动构建 Angular 项目 (2) 将其移至扩展目录 (3) 重新打包扩展 (4) 在浏览器中重新加载扩展 (5) 重新加载所需的页面。因此,我的 DOM 插入部分确实包含了一个用于大部分内容的 iframe,这样我就可以更轻松地更改它。

但是为了解决您的问题,我确实在页面中插入了

webpage-script.js
,以便我可以在 iframe 和网页之间使用 事件侦听器,以便我可以传递数据并保持同步。

// Add event listeners into the Overleaf page that can respond to events from
// our external site.
window.addEventListener('message', (e) => {
  const {data} = e
  const parsedEvent = data
  const parsedData = parsedEvent.data
  switch (parsedEvent.type) {
    case 'rafflesia_copy':
      navigator.clipboard.writeText(parsedData)
      break;
    // ...
  }
})

我的 Angular 服务可以创建类型化

Event
对象并与网页通信:

  copy() {
    if (!this.bibtex) return // Nothing
    const msg: Event = {
      type: 'rafflesia_copy',
      data: this.bibtex
    }
    window.parent.postMessage(msg, '*')
  }

这也可以反过来发生:

ngOnInit(): void {
    window.addEventListener('message', e => {
      const parsedEvent = e.data
      if (parsedEvent?.type === 'rafflesia_getProjectFiles') {
        const files = parsedEvent.data.map((x: any) => x.name)
          .filter((x: string) => x.endsWith('.bib'))
        this.mainbib = files
      }

      if (parsedEvent?.type === 'rafflesia_read') {
        this.draft = parsedEvent.data
        this.parse()
      }
    })

    this.refreshProjectFiles()
  }

它确实会导致需要构建更多文件,并需要跟踪更多文件,但它改进了构建和迭代过程。

© www.soinside.com 2019 - 2024. All rights reserved.