热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

chrome扩展程序_Chrome扩展程序:弥合各层之间的差距

chrome扩展程序构建Chrome扩展程序很容易,而且从很多方面来说都是如此。该文档确实做得很好,并且包含大量示例。另外,检查已安装的任

chrome扩展程序

构建Chrome扩展程序很容易,而且从很多方面来说都是如此。 该文档确实做得很好,并且包含大量示例。 另外,检查已安装的任何组件以查看其背后的魔力很容易。 另一个很大的优点是,它全都是Javascript,CSS和HTML,并带有Chrome API的额外奖励,可让您额外获得一点点魔术。

最近,我不得不为我的公司开发一个工具栏,该工具栏必须阅读当前查看的页面,显示一些SEO信息,进行一些AJAX调用等。 并不是很困难,但是我确实发现了一个没有得到充分记录的问题(如果有的话)。

在继续进行之前,如果您对Chrome扩展程序的开发不完全了解,建议您阅读本概述 。 您将了解有关架构多层之间的复杂性的更多信息。

问题

我决定通过在每个网页中注入iframe来加载扩展程序的UI元素(如工具栏和其他弹出窗口)。 考虑到这一点,在多个iframe ,当前DOM,Chrome后台Javascript文件和Chrome提供的其他层之间进行通信并不是一件容易的事。

实际上,问题出在使用iframe上 。 我必须通过JSON对象从Background层向任何iframe发送大量数据,反之亦然。 由于跨域限制,无法通过页面中插入的内容脚本来操纵iframe

例如,当前查看的页面URL是

http://www.example.com

并且注入的iframe URL是

chrome-extensions:// uniqueidmadeoutoflotsandlotsofletters

两者之间的通信是不可能的,因为跨域通信是一个很大的问题。

那么为什么要使用iframe?

好吧, iframe是(当前)隔离大量Javascript,CSS和HTML的唯一方法,而不受当前网页样式和行为的影响。

另外,我很固执,以为可能存在一种以优雅的方式在所有层之间进行通信的方法。 即使我在Google或StackOverflow上找不到答案。

有什么解决办法?

使用Chrome API方法chrome.tabs.sendMessage从“背景”层发送消息时,该消息将发送到所有帧,而不仅仅是发送了ContentScript的消息。

我不知道为什么我没有想到这一点!

由于它的ContentScript内喷射的内部框架 ,而且能获得到Chrome API。

因此, iframe可以使用默认的DOM方法window.parent.postMessage与其父ContentScript进行对话,并通过chrome.extension.sendRequest与Background层进行对话,并且还可以使用chrome.extension.onMessage来监听Background层消息。 addListener方法

如何实现?

这个想法很简单:我创建了一组接待员 ,负责处理从一层到另一层的所有消息传输。

当前,这是我设置各层角色的方式:

背景(请参阅background.js)

可以从ContentScript接收消息,然后将它们重定向到适当的iframe或处理消息。

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

可以将消息发送到所有框架(ContentScript和iframe )。

ContentScript(请参阅inject.js)

可以同时从Background层和iframe接收消息。

当来自iframe时 (通过默认的window.postMessage方法),它将消息重定向到Background(如果指定)。 如果未指定,它将处理该消息。

只能将消息发送到后台。

iframe(请参阅iframe.js)

可以从唯一的Background层接收消息,然后检查它是否适合他,然后处理该消息。

可以使用window.parent.postMessage将消息发送到ContentScript。

换句话说:

–背景与ContentScript和iframe对话,但仅收听ContentScript。

– ContentScript侦听Background和iframe ,但仅侦听Background。

iframe与ContentScript对话并收听背景。

旁注:我知道Background也可以侦听iframe消息,但是在我的示例中,由于没有必要,因此我跳过了这个概念。

区分iframe

每个iframe都有一个唯一的ID(在下面的示例中称为View ),因此很容易将消息重定向到特定的iframe 。 一种简单的方法是在加载iframe时在URL中添加一个属性,如下所示:

chrome.extension.getURL('html/iframe/comment.html?view=comment’);

讯息设定

传递的消息是包含两个属性的简单对象:

- 信息

–数据

每层(背景,ContentScript和IFrame)都有一个tell方法,该方法发送带有两个属性的消息。

tell(‘tell-something’, {attribute1:’a’, attribute2:’b’});

iframe发送消息时,当前iframe 视图ID也会作为data中属性发送

tell(‘tell-parent-something’, {source:’comment’});

当需要将消息发送到特定的iframe时 ,将在数据中添加带有正确视图IDview属性。

tell(‘tell-to-an-iframe’, {
view:’comment’,
title:’hello world!’
});

如果需要将邮件发送到所有iframe ,则可以使用“ *”通配符。

tell(‘tell-to-all-iframes’, {view:’*’, title:’foo bar’});

如果未指定视图,则应由ContentScript / Background处理消息。

现在,这个例子(最后)!

我为喜欢我称为iHeart的页面创建了一个简单的扩展名(您可以在github上找到源代码)。

例

这是一个简单的按钮,在屏幕左侧有一个心形。 单击后,用户可以添加评论并保存。 保存的页面将在扩展弹出按钮中列出:

心形按钮

坚韧的细节

每层都有自己的告诉监听方法:

背景

_this.tell = function (message, data){
var data = data || {};
chrome.tabs.getSelected(null, function (tab){
if (!tab) return;
chrome.tabs.sendMessage(tab.id, {
message   : message,
data : data
});
});
};

倾听

function onPostMessage (request, sender, sendResponse){
if (!request.message) return;
if (request.data.view){
_this.tell(request.message, request.data);
return;
}
processMessage(request);
};

内容脚本

function tell (message, data){
var data = data || {};
// send a message to "background.js"
chrome.extension.sendRequest({
message : message,
data : data
});
};

倾听

// messages coming from iframes and the current webpage
function dom_onMessage (event){
if (!event.data.message) return;
// tell another iframe a message
if (event.data.view){
tell(event.data);
}else{
processMessage(event.data);
}
};
// messages coming from "background.js"
function background_onMessage (request, sender, sendResponse){
if (request.data.view) return;
processMessage(request);
};

iframe

_this.tell = function (message, data){
var data = data || {};
data.source = _view;
window.parent.postMessage({
message   : message,
data : data
}, '*');
};

倾听

function background_onMessage (request, sender, sendResponse){
// make sure the message was for this view (you can use the "*" wildcard to target all views)
if (
!request.message ||
!request.data.view ||
(request.data.view != _view && request.data.view != '*')
) return;
// call the listener callback
if (_listener) _listener(request);
};

通信过程非常简单。 当您访问网页并看到所看到的内容时(它可以是任何东西,这是您想要的,我不会判断),然后单击iHeart按钮。 然后,该按钮指示打开评论iframe。

js / iframe / heart.js

function heart_onClick (event){
$('.heart').addClass('active');
_iframe.tell('heart-clicked');
};

然后,它在ContentScript中处理消息并打开注释弹出窗口。

js / inspect.js

function processMessage (request){
if (!request.message) return;
switch (request.message){
case 'iframe-loaded':
message_onIframeLoaded(request.data);
break;
case 'heart-clicked':
message_onHeartClicked(request.data);
break;
case 'save-iheart':
message_onSaved(request.data);
break;
}
};
...
function message_onHeartClicked (data){
var comment = getView('comment');
comment.iframe.show();
tell('open-comment', {
view:'comment',
url:window.location.href,
title:document.title
});
};

出现注释弹出窗口,并在注释框下方显示当前网页标题。

js / iframe / comment.js

function onMessage (request){
switch (request.message){
case 'open-comment':
message_onOpenComment(request.data);
break;
case 'website-is-hearted':
message_onIsHearted(request.data);
break;
}
};
...
function message_onOpenComment (data){
$('.page-title').html(data.title);
};

按下保存按钮后,注释iframe会将信息发送回ContentScript。

js / iframe / comment.js

function save_onClick (event){
var comment = $('#comment').val() || '';
_iframe.tell('save-iheart', {
comment   : comment
});
};

ContentScript隐藏注释iframe,并告诉Background保存整个内容。

js / inject.js

function message_onSaved (data){
var comment = getView('comment');
comment.iframe.hide();
tell('save-iheart', {
url:window.location.href,
title:document.title,
comment:data.comment
});
};

最后,Background通过将网站保存为数组来最终确定所有细节。

js / background.js

function onPostMessage (request, sender, sendResponse){
if (!request.message) return;
if (request.data.view){
_this.tell(request.message, request.data);
return;
}
switch (request.message){
case 'save-iheart':
message_onSaved(request.data);
break;
case 'all-iframes-loaded':
message_allIframesLoaded(request.data);
break;
}
};

function message_onSaved (data){
_websites.push({
url           : data.url,
title         : data.title,
comment       : data.comment
});
};

……接待员做了他们的工作

就是这样。 那是我解决多种类型的层之间的通信问题的解决方案,这并不难……

现在,如果我可以轻松解决个人关系中的沟通问题,那就太好了,谢谢:P

通过处理数据验证,将喜欢的网页保存在数据库中,动态调整iframe内容的大小,为扩展添加一些动画以使其使用更加有趣,可以进一步处理该示例。 所有这些都很棒,并且已经可以实现,但这超出了本文的范围。

翻译自: https://www.sitepoint.com/chrome-extensions-bridging-the-gap-between-layers/

chrome扩展程序



推荐阅读
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 本文介绍了2015年九月八日的js学习总结及相关知识点,包括参考书《javaScript Dom编程的艺术》、js简史、Dom、DHTML、解释型程序设计和编译型程序设计等内容。同时还提到了最佳实践是将标签放到HTML文档的最后,并且对语句和注释的使用进行了说明。 ... [详细]
  • 关于extjs开发实战pdf的信息
    本文目录一览:1、extjs实用开发指南2、本 ... [详细]
  • 表单代码 ... [详细]
  • 最近学习了关于使用最为流行的jquery发送请求,在实践中以最为简单的聊天室作为测验的辅助工具,对相关网页开发有一个初步的认识,希望大家能够一起学习进步。首先介绍一下 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 在Android中解析Gson解析json数据是很方便快捷的,可以直接将json数据解析成java对象或者集合。使用Gson解析json成对象时,默认将json里对应字段的值解析到java对象里对应字段的属性里面。然而,当我们自己定义的java对象里的属性名与json里的字段名不一样时,我们可以使用@SerializedName注解来将对象里的属性跟json里字段对应值匹配起来。本文介绍了使用@SerializedName注解解析json数据的方法,并给出了具体的使用示例。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • 一、Struts2是一个基于MVC设计模式的Web应用框架在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts2优点1、实现 ... [详细]
  • XMLhttpREquest_Ajax技术总结之XmlHttpRequest
    Ajax1、 什么是ajax   ... [详细]
  • 我将SpringMVC升级到Spring3.2.5.我的一些剩余调用即使存在,也会返回无法识别的字段异常.这是错误.Resolvingexceptionfrom ... [详细]
  • asp.net(vb脚本)如何获取xml的节点值?xmlversion1.0encodingutf-8?rootimageimagemenusmenuurl#frame_paren ... [详细]
author-avatar
RAL-1314921
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有