chrome 扩展是用传统的 HTML、CSS、JS、图片等静态资源开发并最终打包成后缀为 .crx
的一个压缩包。因此,它和咱们日常开发的页面没有多大的区别,因此若是你想引入前端开发所用的各类框架,组件库,构建工具也都是能够的。主要区别只有 2 个:javascript
扩展的安装方式有 3 种:css
.crx
压缩包,把压缩包直接拖拽到 chrome 的扩展管理页面这里只简单地介绍几种常常见到的,还有更多的展示形式,你们感兴趣能够去官方文档详细了解html
Octotree
(对 gitub 项目页面作导航)vue-devtool
等框架提供的调试工具具体扩展各个组成部分的学习,咱们以一个很简单的例子为基础进行介绍,这个扩展是一个为页面添加回到顶部功能的扩展。前端
每个扩展都必需要有的一个名字为 manifest.json 的配置文件,这个文件声明了此扩展用到了哪些功能,及各个功能须要用到的静态资源vue
这个 backToTop 扩展的配置已经在途中说明,已经有了基本的说明,下面对一些配置项作下额外的说明,所有配置能够在官网查看:java
chrome.pageAction
API 来动态的设置扩展在某些页面的行为这部分咱们说下扩展开发核心的几种 JSgit
popup 页面生命周期是点击弹出时,初始化,关闭时,页面也跟着销毁, 而且这个页面没有任何跨域的限制。它在咱们扩展里的做用是配置页面里 backToTop icon 的样式,并存入storage。web
chrome.storage.local.get(['right', 'bottom', 'icon'], function(result) {
if(result) {
// 初始化
right.value = result.right || '';
bottom.value = result.bottom || '';
if(result.icon) {
img.src = result.icon;
img.dataset.uploaded = true;
}
}
})
复制代码
页面初始化时,从 storage 取出存储的值,初始化页面。 保存参数时,再将相关参数存入 storagechrome
chrome.storage.local.set({right: rightVal, bottom: bottomVal});
if(img.dataset.uploaded) {
chrome.storage.local.set({icon: img.src});
}
复制代码
注: storage API 有 2 种 storage.sync
和 storage.local
他们的区别json
localstorage
是同样的 5M. 而 sync 存储的大小只有 100K 并且对于单个 key 的值大小,以及写入的频率也有限制,毕竟要同步服务端,因此若是开发的扩展只是用于我的使用的效率提高,不打算发布,能够直接用 local 就行了content-script
是咱们用来定制化页面,实现页面内扩展逻辑的地方。它的特色是:
content-script
建立一个 script 标签插入到 DOM 里 这个新的 script 里的函数是能够绑定的content-script
会在每个 tab 页面里都有一份代码在运行content-script
才会开始运行。那咱们的 backToTop 里 content-script
都干了什么呢 首先,初始化咱们页面里的 icon 并根据页面 scrollTop
判断当前是否须要展现 icon
const el = document.createElement('div');
el.show = true; // 控制icon是否显示
el.classList.add('ce-btt-container');
el.style.opacity = target.scrollTop > visibleHeight ? 1 : 0;
const img = document.createElement('img');
img.classList.add('ce-btt-icon');
el.appendChild(img);
chrome.storage.local.get(['right', 'bottom', 'icon'], function(result) {
el.style.right = result && result.right ? result.right + 'px' : right;
el.style.bottom = result && result.bottom ? result.bottom + 'px' : bottom;
img.src = result && result.icon ? result.icon : chrome.runtime.getURL('icons/backToTop.png');
document.body.appendChild(el);
});
复制代码
第二步, 要想实现返回顶部,固然要给咱们的 icon 绑定点击事件,以及监听 scroll
事件判断何时该隐藏展现
el.addEventListener('click', function(e) {
let step = 20;
let timer = setInterval(() => {
if(target.scrollTop <= 0) {
clearInterval(timer);
} else {
step += 20;
target.scrollTop -= step;
}
}, 20);
});
const handleScroll = function() {
if(!el.show) return false; // icon不显示时,不处理
if(target.scrollTop > visibleHeight) {
el.style.opacity = 1;
} else {
el.style.opacity = 0;
}
};
container.addEventListener('scroll', throttle(handleScroll, 300));
复制代码
第三步, 若是 popup 页面有配置的变动, content-script
都须要马上进行更新
chrome.storage.onChanged.addListener(function(changes, namespace) {
if(changes.bottom) {
el.style.bottom = `${changes.bottom.newValue}px`;
}
if (changes.right) {
el.style.right = `${changes.right.newValue}px`;
}
if (changes.icon) {
img.src = changes.icon.newValue;
}
});
复制代码
注: 这里须要注意的是,由于咱们要把扩展里的 icon 插入到页面,因此须要在 manifest.json
里配置 web_accessible_resources
赋予页面能够访问咱们指定的扩展静态资源的权限。这是由于页面里 icon 的 src 属性是这样的
background
能够理解为是扩展在后台一直运行的一个 JS(实际并非), 它在整个浏览器里只会有一个 js 在运行。在 background 的配置里,有一个 persistent
的配置, 当它为 true 时,background 才会一直运行,false 时,浏览器会检测长时间不活动时,自动卸载调,只有监听的事件发生时,才会从新执行,官方的说明是
The only occasion to keep a background script persistently active is if the extension uses chrome.webRequest API to block or modify network requests. The webRequest API is incompatible with non-persistent background pages.
因此绝大多数时候,咱们把它设为 false 就能够了。另外 background
也是能够跨域的, 因此咱们能够总结出,除了页面内的 js chrome 对其余的 js 都没有跨域的限制。
好,咱们看看咱们扩展里 background
干了啥
首先,初始时,确定要监听浏览器的初始化事件,才能够绑定扩展关注的事件。
chrome.runtime.onInstalled.addEventListener(function() {
// init extention
})
复制代码
第二步,由于有的页面已经提供了返回顶部的功能,因此这个时候咱们须要提供能够把咱们的 icon 永久隐藏的功能,咱们在 background
初始化的逻辑中,建立一个鼠标右键的菜单项,这个菜单项能够实现 切换咱们的 icon 显示状态的功能
chrome.contextMenus.create({
title: 'toggle',
id: 'toggle'
});
chrome.contextMenus.onClicked.addListener(function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
sendMsg(tabs.length ? tabs[0].id : null);
});
});
function sendMsg(tabId) {
chrome.tabs.sendMessage(tabId, 'toggle', function(res) {
console.log(res);
});
}
复制代码
发送消息这里咱们用了 chrome.tabs
API 由于咱们每一个 tab 都会有一个 content-script
因此须要筛选出当前所在的标签页,而后发送消息。
最后,咱们的 content-script
须要监听发送消息的事件,并切换 icon 的状态
chrome.runtime.onMessage.addListener(function(req, sender, respond) {
if(req === 'toggle') {
if (target.scrollTop > visibleHeight) {
el.style.opacity = el.style.opacity === '1' ? 0 : 1;
}
el.show = !el.show;
respond('toggle success');
}
});
复制代码
至此,整个扩展的功能就基本介绍完了,过程当中用到的 API 这里并不做详细的介绍,详细使用仍是须要你们去 官网 查看
最后说一下如何调试,调试我的认为仍是比较麻烦的, 代码变动并无热更新,因此须要咱们手动去扩展管理页从新加载。并且几种不一样的 JS 调试的位置也不一样,设计通信时常常须要在几个不一样的地方来回切换
popup
调试:在弹出的窗口里,右键审查元素就能够弹出调试窗口,调试方式和普通的页面调试没有区别。
background
调试: 在管理页点击背景页,就能够弹出调试窗口了
content-script
调试: 由于是在页面运行,因此调试的地方和页面 js 是在一个窗口里
代码位置:在 sources tab 下选中 Content scripts 就能够看到页面加载的所有的扩展 contnt-script
了。
console 输出: 在 Console tab 下拉框里选中要调试的扩展,就能够看到对应扩展的 console 输出。
在扩展管理页,能够打包扩展程序,打包后就能够生成 .crx
文件
打包以后,就能够发布了,不过发布须要先花 5$ 注册开发者,我就没有继续下去了。
在开发过程当中,能够发现写一个扩展其实并不难,用到的技术都是前端天天都在用的东西。只要咱们多加留心,就会发现使用 chrome 过程当中有许多能够提效,优化体验的地方,这时候咱们就能够试着用扩展的方式解决。整体来讲,chrome 扩展是一种技术成本很低,就能够干些有趣的事情的技术
参考资料: