【教程向】从零开始创建浏览器插件(三)解决 Chrome 扩展中弹出页面、背景脚本、内容脚本之间通信的问题

第三步:解决 Chrome 扩展中弹出页面、背景脚本、内容脚本之间通信的问题

Chrome 扩展开发中,弹出页面(Popup)、背景脚本(Background Script)、内容脚本(Content Script)各自拥有独立的 JavaScript 执行环境。这种设计可以增强安全性,但同时也带来了数据共享和传递上的问题。

本文将详细探讨弹出页面、背景脚本、内容脚本之间的通信方式,并提供解决方案的代码示例。

在这里插入图片描述

问题概述

弹出页面、背景脚本、内容脚本的独立运行环境带来了以下问题:

  1. 数据共享难题:它们各自拥有不同的执行环境,无法直接访问彼此的 JavaScript 变量或对象。
  2. 事件监听问题:弹出页面关闭后,其事件监听器会被卸载,无法保持持久监听状态。
  3. 权限隔离:内容脚本与弹出页面的权限各自独立,内容脚本无法直接访问弹出页面的 DOM 元素,反之亦然。

解决方案:相互通信的方式

Chrome 扩展提供了多种通信方式来解决这些问题:

1. 使用 chrome.runtime 消息传递

chrome.runtime API 提供了弹出页面、背景脚本和内容脚本之间通信的机制。

弹出页面与背景脚本的通信

背景脚本 (background.js):

// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "getData") {
        // 获取数据并通过 sendResponse 返回给弹出页面
        const data = {info: "background data"};
        sendResponse(data);
    }
    return true;
});

弹出页面 (popup.js):

// popup.js
document.addEventListener("DOMContentLoaded", function () {
    // 向背景脚本请求数据
    chrome.runtime.sendMessage({type: "getData"}, (response) => {
        console.log("Received data from background:", response);
    });
});
内容脚本与背景脚本的通信

背景脚本 (background.js):

// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "fetchContentData") {
        // 从后台处理数据并返回给内容脚本
        const data = {content: "Processed data from background"};
        sendResponse(data);
    }
    return true;
});

内容脚本 (content.js):

// content.js
chrome.runtime.sendMessage({type: "fetchContentData"}, (response) => {
    console.log("Received data from background:", response);
});
弹出页面与内容脚本的通信

直接通信方式不可行,但可以通过背景脚本作为中介实现通信。

弹出页面 (popup.js):

// popup.js
function sendMessageToContentScript(tabId, message) {
    chrome.tabs.sendMessage(tabId, message, (response) => {
        console.log("Response from content script:", response);
    });
}

document.addEventListener("DOMContentLoaded", function () {
    chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
        sendMessageToContentScript(tabs[0].id, {type: "greeting", text: "Hello from popup!"});
    });
});

内容脚本 (content.js):

// content.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "greeting") {
        console.log("Received message from popup:", message.text);
        sendResponse({text: "Hello from content script!"});
    }
});

2. 使用 chrome.storage 共享数据

chrome.storage API 允许持久化并共享数据,以便在不同环境间传递。

背景脚本 (background.js):
// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "saveData") {
        chrome.storage.local.set({sharedData: message.data}, () => {
            sendResponse({status: "Data saved"});
        });
    } else if (message.type === "loadData") {
        chrome.storage.local.get("sharedData", (result) => {
            sendResponse({data: result.sharedData});
        });
    }
    return true;
});
弹出页面 (popup.js):
// popup.js
document.addEventListener("DOMContentLoaded", function () {
    // 向背景脚本请求数据
    chrome.runtime.sendMessage({type: "loadData"}, (response) => {
        console.log("Data loaded from storage:", response.data);
    });

    // 保存数据到 storage
    chrome.runtime.sendMessage({type: "saveData", data: "New shared data"}, (response) => {
        console.log(response.status);
    });
});
内容脚本 (content.js):
// content.js
chrome.runtime.sendMessage({type: "loadData"}, (response) => {
    console.log("Data loaded from storage:", response.data);
});

3. 使用 chrome.tabs API 与当前活动标签通信

chrome.tabs API 可以帮助我们确定活动标签,并使用 chrome.scripting 在该标签中注入代码。

弹出页面 (popup.js):
// popup.js
document.addEventListener("DOMContentLoaded", function () {
    chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
        chrome.scripting.executeScript({
            target: {tabId: tabs[0].id},
            func: () => {
                document.body.style.backgroundColor = "pink";
            }
        });
    });
});

总结

由于 Chrome 扩展的不同脚本运行环境是相互独立的,所以开发者在设计扩展时需要使用不同的通信机制来确保数据共享和功能协同。本文提供了多种解决方案,开发者可以根据需求选择最合适的方式:

  1. chrome.runtime 消息传递
  2. chrome.storage 数据持久化
  3. chrome.tabs 标签控制与代码注入

希望本文能够帮助你在 Chrome 扩展开发中更好地处理弹出页面、背景脚本和内容脚本之间的通信问题!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/613034.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

word转pdf的java实现(documents4j)

一、多余的话 java实现word转pdf可用的jar包不多,很多都是收费的。最近发现com.documents4j挺好用的,它支持在本机转换,也支持远程服务转换。但它依赖于微软的office。电脑需要安装office才能转换。鉴于没在linux中使用office,本…

hadoop学习---基于Hive的教育平台数据仓库分析案例(二)

衔接第一部分,第一部分请点击:基于Hive的教育平台数据仓库分析案例(一) 后接第三部分,第三部分请点击:基于Hive的教育平台数据仓库分析案例 (三) 意向用户模块(全量分析)&#…

用户体验优化uxo指的是什么?

用户体验优化(User Experience Optimization,简称UXO)是一种专注于改善和提升用户在使用企业产品或服务时的整体感受和体验的过程。简单来说,它旨在通过改进产品或服务的设计和功能,使用户在使用过程中感到更加愉悦、满意和高效。用户体验优化…

桌面怎么分类便签 桌面分类便签设置方法

桌面便签,一直是我工作和学习的好帮手。每当灵感闪现或是有待办事项,我都会随手记录在便签上,它们就像我桌面上的小助手,时刻提醒我不要遗漏任何重要事务。 但便签一多,管理就成了问题。一张张五颜六色的便签贴满了我…

C++ 多态的相关问题

目录 1. 第一题 2. 第二题 3. inline 函数可以是虚函数吗 4. 静态成员函数可以是虚函数吗 5. 构造函数可以是虚函数吗 6. 析构函数可以是虚函数吗 7. 拷贝构造和赋值运算符重载可以是虚函数吗 8. 对象访问普通函数快还是访问虚函数快 9. 虚函数表是什么阶段生成的&…

华为与达梦数据签署全面合作协议

4月26日,武汉达梦数据库股份有限公司(简称“达梦数据”)与华为技术有限公司(简称“华为”)在达梦数据武汉总部签署全面合作协议。 达梦数据总经理皮宇、华为湖北政企业务总经理吕晓龙出席并见证签约;华为湖…

uniapp、web网页跨站数据交互及通讯

来来来,说说你的创作灵感!这就跟吃饭睡觉一样,饿了就找吃的,渴了就倒水张口灌。 最近一个多月实在是忙的没再更新日志,好多粉丝私信说之前的创作于他们而言非常有用!受益菲浅,这里非常感谢粉丝…

Ubuntu20.04 设置路由器

1. 网络拓扑图 2. 查看网卡信息 ip a得出如下网卡信息&#xff0c;enp1s0和enp2s0为两个网卡名称&#xff0c;以及相关两个网卡的详细信息&#xff0c;不同设备的网卡名称可能不一样 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group defaul…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.4讲 GPIO中断实验-IRQ中断服务函数详解

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

debug技巧之本地调试

大家好啊&#xff0c;我是summo&#xff0c;今天给大家分享一下我平时是怎么调试代码的&#xff0c;不是权威也不是教学&#xff0c;就是简单分享一下&#xff0c;如果大家还有更好的调试方式也可以多多交流哦。 如果看过我文章的同学应该知道我是一个Java开发&#xff0c;平时…

FANUC机器人工具坐标偏移的用法

一、工具坐标偏移的使用场景 在机器人位置不改变的情况下&#xff0c;工业机器人使用默认工具坐标系示教的一系列运动点位&#xff0c;要保持原本点位位置不变的情况下&#xff0c;改变机器人工具坐标的参数&#xff0c;就要用到机器人坐标转化的功能。在FANUC机器人上体现为机…

/swagger/index.html#/ 的页面可能存在问题,或者已永久移动到新的网址。

问题背景 在golang的项目中&#xff0c;使用了swagger。在另外一个项目中也使用了swagger,没有发生过这个问题。新的项目中&#xff0c;用了和之前项目同样的web框架&#xff0c;仔细比对了和之前项目的差异&#xff0c;只不过&#xff0c;目录结构做了调整&#xff0c;所以&a…

网络编程套接字 (二)---udosocket

本专栏内容为&#xff1a;Linux学习专栏&#xff0c;分为系统和网络两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握Linux。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;网络 &#x1f69a;代码仓库&#xff1a;小小unicorn的代…

Springboot集成Eureka实现注册中心-11

Spring Cloud Netflix Eureka是Spring Cloud Netflix子项目的核心组件之一&#xff0c;主要用于微服务架构中的服务治理。 什么是注册中心 在微服务架构中往往会有一个注册中心&#xff0c;每个微服务都会向注册中心去注册自己的地址及端口信息&#xff0c;注册中心维护着服务…

泰迪智能科技大数据开发实训平台功能介绍

大数据开发实训平台是面向实训课和课后训练的编程实训平台&#xff0c;平台底层基于Docker技术&#xff0c;采用容器云部署方案&#xff0c;预装大数据相关课程教学所需的实训环境&#xff0c;拥有1主2从的Hadoop集群&#xff0c;还能够自主定制环境&#xff0c;并能够与实训管…

10.轮转数组

文章目录 题目简介题目解答解法一&#xff1a;使用额外的数组代码&#xff1a;复杂度分析&#xff1a; 解法二&#xff1a;数组反转代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 轮转数组 相关的讲解&#xff01;&#…

基于VOLOPV2的自动驾驶环境感知系统

基于VOLOPV2的自动驾驶环境感知系统是一个复杂的系统&#xff0c;它主要负责实时检测并识别周围环境中的各种物体和信息&#xff0c;为自动驾驶车辆提供必要的感知数据。以下是对该系统的一个简要介绍&#xff1a; 环境感知是自动驾驶系统中的一个关键部分&#xff0c;它依赖于…

SQL的命令

目录 创建用户 ​编辑 DDL数据库操作 查询 创建 使用 删除 创建数据库表 在表中修改字段 查询表 DML 添加数据 修改 删除 DQL 查询 创建用户 DDL数据库操作 查询 show databases; 创建 权限问题导致无法创建&#xff0c;连接root修改用户权限 CREATE DATABAS…

AJAX概述和基本使用

01 【AJAX概述和基本使用】 1.AJAX简介 AJAX 全称为Asynchronous JavaScript And XML&#xff0c;就是异步的JS 和XML 通过AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据 AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准…

Java入门基础学习笔记8——注释

1、注释&#xff1a; 注释是写在程序中对代码进行解释说明的文件&#xff0c;方便自己和其他人查看&#xff0c;以便理解程序的。 package cn.ensource.note;/**文档注释文档注释 */ public class NoteDemo {public static void main(String[] args) {// 单行注释System.out.…