24
头图

记一次前端"chrome扩展"简单易懂的实战分享会(上)

记录了我在组内的技术分享, 有同样需求的同学可以参考一下
分享全程下来时间大约67分钟

image

一. 为啥要学这个

身为前端工程师,浏览器是我们的主战场, 而我们不但要会使用浏览器, 还要利用浏览器, 核心是学习浏览器的一些编程思维,让我们更加厉害。
当然了看的见的好处就是我们可以利用chrome的扩展技术做一些好玩的小工具陶冶情操。
本文没有大型的概念, 目的是让你最轻松, 最快速的学会开发插件.

本文主要讲述干货主要知识,小知识点有没覆盖到的请查阅官网,如果是一个初学者理解完本篇文章也具备了开发的能力。

二. 什么样的'文件'算chrome扩展

没学习相关知识之前,以为需要是某些特定后缀的文件才是扩展程序类似我之前分享过的vscode插件vscode插件开发, 而chrome的扩展只需要一个json入口文件即可, 当然如果你要发到chrome商店的话还是需要打包一下的。
而这主要的入口文件就是manifest.json名字必须叫这个。
如下内容:

{
  "manifest_version": 2, // 使用的哪个版本的规则开发扩展
  "name": "谷歌扩展", // 这个是要显示在插件页面的
  "description": "用于分享知识", // 插件的介绍
  "version": "1.0", // 这个版本号会显示在插件下面, 所以不是随便填写的
  "browser_action": {
    "default_icon": "images/qian.png" // 默认显示的图片
  }
}

"manifest_version" 使用1的话会报错, 所以现在都用2了.

为存放相关图片, 我们建立图片文件夹
image.png

是不是不太相信, 这就完成了一个最最基本的'插件'

打开开发者模式
image.png

在控制页面导入这个插件
image.png

导入我们开发的相关文件夹, 也就是manifest.json存放的文件夹
image.png

插件已经生效了, 我们把他放到外面便于使用, 如图步骤:
image.png

现在我们就获得了属于我们自己的谷歌插件
image.png

三. 更新插件

这里更新单拿出来说, 是为了方便汇总, 看到后面大家也可以来这里查, 当然下面也会重复说相关操作

image.png

  1. 更新插件, 请点击2, 点击1也可以做到更新, 但是他是更新全部, 哪怕只有一个扩展他也会联网请求更新, 浪费半分钟的时间, 只有在电脑断网的情况下才会立刻更新本地插件, 所以你懂他的更新机制了吧, 所以开发时候推荐选用2的方法更新插件.
  2. devtools: 需要f12关闭控制台, 再f12打开控制台才可以更新, 并且不可以是chrome://extensions/, 需要选择一个有效的网址.
  3. background: 每次更新插件或者重开浏览器才刷新, 关闭某个页面是不会刷新的.
  4. popup: 每次点击都是重新加载popup程序

四. background 的概念和玩法

我们插件跑在用户的浏览器上, 那么它当然也会存在一个背后运行的后台控制系统, 要不然怎么操控这个插件?
而这个控制系统就是background, 我们在manifest.json里面加上一条

  "background":
    {
    "page": "background/background.html" // 指向我们的后台系统
  },

我们新增一个background文件夹, 里面就来编写我们的后台系统吧

注意这里可以是 "background/background.html" 也可以是"background/background.js", 差别就是后台管理页面有无dom结构的存在, 下面有例子.

如果你指向的是一个js文件, 那么系统会给我们一个默认的空的html文件引入js文件作为后台.

image.png

我们更新扩展, 就会发现扩展下面出现了查看视图
image.png

点击后你回发现他只是个控制台, 并没有什么实际的操作, 而且也没有相应的视图页面, 但是我们有console就可以开始玩耍了, 因为部分组件里面的console都是现在这里的.

五. 显示图标的玩法

悬浮显示文字

manifest.json里面"browser_action"加上这句配置
"default_title": "悬停会显示我",
image.png

这就可以为用户说明你这个图标表示的是什么用途了

显示文字

悬浮才显示那也太不直观了, 我们直接在图标上显示出文字岂不美哉?
这是我们调用的第一个api, 庆祝一下吧.
background.js

  chrome.browserAction.setBadgeText({text: '你懂'});
  chrome.browserAction.setBadgeBackgroundColor({color: 'red'});

image.png

  1. chrome这个变量是全局自带的, 直接调用也不会出错放心吧
  2. chrome.browserAction.setBadgeText 最大长度为4, 中文超过两个也显示不下了, 所以中文最多两个.
  3. background.js不可以内嵌在background.html页面里面, 会报安全权限的错误
悬浮的文字也可以设置, 那我们就做一下实时更新的效果
chrome.browserAction.setBadgeText({ text: '你懂' });
chrome.browserAction.setBadgeBackgroundColor({ color: 'red' });


let n = 1;

setInterval(() => {
    chrome.browserAction.setBadgeText({ text: 'n' + ++n });
    chrome.browserAction.setTitle({ title:'说明' + ++n });
    console.log(n);
}, 1000)

image.png

而我们的控制台, 也打印出了相应的console, 我们之后的开发调试同样要在这里进行了
image.png

可以想象, 比如你监控到页面有问题, 那么你可以用红色把错误的数量显示出来, 然后悬浮显示这个报错是说明什么, 是不是还挺方便的, 至于如何监控我们下面会讲.

六. popup的展示方式

也就是我们上面学习的小图标, 点击后出现的下拉框, 用户可以在这里进行基础的交互.

manifest.json里面"browser_action"加上这句配置
"default_popup": "popup/index.html",

新建popup文件夹, index.html文件代码为下面的

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #content {
      border: 1px solid red;
      padding: 10px;
    }
  </style>
</head>
<body>
  <button id="bt">点击更新内容</button>
  <div id="content"> 显示内容 </div>
  <script src="./index.js"></script>
</body>
</html>

刷新扩展我们可以点击icon查看下效果, 很奇怪哦

image.png

  1. div会独占一行, 但是他并不会撑起宽度, 我们需要自己为最外层设置宽度.
  2. position: fixed; left: 0; top: 0; 效果是奇怪的, 他会已popup本身dom为坐标系进行定位, 所以慎用!

自定义宽高后舒服多了

    body{
      width: 300px;
      height: 300px;
    }

image.png

为按钮添加点击事件

这里同样不能用内联的js, 要用外部引入的.
index.js :

const oBt = document.getElementById('bt');
const oContent = document.getElementById('content');

oBt.addEventListener('click', ()=>{
  alert('点击了按钮');
  oContent.innerHTML = "我是改变后的文字"
})

image.png
image.png

这样我们对popup内的dom就可以操作了, 但是我想让我们的图标上显示的文字 停下来我要怎么做那?

七. popup与background的通信-> extension

这里涉及到一个概念, background与popup都是独立的页面, 所以想要通讯只能用系统提供的api实现

chrome.extension.getBackgroundPage() 可以获取到Background页面的上下文的window属性.

第一步: 我在background.js里面加了实时更新icon文字的限制, 只有showTime为真才会去更新

chrome.browserAction.setBadgeText({ text: '你懂' });
chrome.browserAction.setBadgeBackgroundColor({ color: 'red' });

let n = 1;
var showTime = true;

setInterval(() => {
  if(showTime){
    chrome.browserAction.setBadgeText({ text: 'n' + ++n });
    chrome.browserAction.setTitle({ title:'说明' + ++n })
  }
}, 1000)

注意, 这里我用var定义showTime, 因为let不会挂在window上会导致访问不到这个变量.

popup/index.js文件我们获取到window对象, 并改变showTime的值

const oBt = document.getElementById('bt');
const bgWindow = chrome.extension.getBackgroundPage();

oBt.addEventListener('click', ()=>{
  // 操作 background的上下文
  bgWindow.showTime = false
  chrome.browserAction.setBadgeText({text: '占领'});
})

改变背景颜色更明显

oBt.addEventListener('click', ()=>{
  alert('点击了按钮');
  oContent.innerHTML = "我是改变后的文字";

  // 操作 background的上下文
  bgWindow.showTime = false
  chrome.browserAction.setBadgeBackgroundColor({ color: 'blue' });
  chrome.browserAction.setBadgeText({text: '占领'});

  // 异步请求
  ajaxGet('https://www.zhangzhaosong.com/', (res)=>{
    console.log('返回值', res)
  })
})

image.png

类似这种用法能不用就不用, 毕竟这种变成思想很反人类, 数据来源搞得模糊不清, 莫名其妙的错误也会纷至沓来.

八. 让我们发起请求

都是本地化的操作肯定无法满足我们, 那我们与服务端的通讯就可以玩起来了
这里出现了一个新概念权限

  "permissions": ["http://*/*", "https://*/*"]

上面的意思是容许访问网址的白名单, 我们可以根据实际情况来做出调整.

popup/index.js:

function ajaxGet(url,fn) {
    let xhr=new XMLHttpRequest();
    xhr.open("GET",url);
    xhr.send();
    xhr.onreadystatechange=function () {
        if (xhr.readyState==4&&xhr.status==200) {
            fn(xhr.responseText);
        }
    }
}

  ajaxGet('https://www.zhangzhaosong.com/', (res)=>{
    console.log('返回值', res)
  })

九. 本地储存的使用

数据不可能每次都向后台请求, 我们为了方便快捷也需要利用浏览器本地的储存方式.

manifest.json文件里面新增一条
"permissions": ["storage", "http://*/*", "https://*/*"]

了不起的chrome.storage.sync, 可以跟随当前登录用户自动同步,这台电脑修改的设置会自动同步到其它电脑;

popup/index.js中添加


let date = new Date();
const Y = date.getFullYear() + '-';
const M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
const D = date.getDate() + ' ';

// 读取的key与这个key的默认值
chrome.storage.sync.get({time: '第一次读取' }, function(items) {
    console.log(items.time);
});

chrome.storage.sync.set({time: Y+M+D}, function() {
    console.log('保存成功!');
});

在popup上点击右键, 直接开启检查
第一次读取的结果
image.png

image.png

第二次点击
image.png

这里大家应该都明白了, 用于存放用户对我们插件的一些基本配置.
比如在popup里面配置好拦截哪些请求, 处理哪些dom的样式, 设置怎样的皮肤, 然后用户下次使用的时候仍然会有这个设置数据.

下篇讲述: 坏插件如何注入的页面, 如何获取用户页面的dom, 以及有趣的想法等等内容, 图片有点多所以越写越卡, 下偏见喽!


lulu_up
5.7k 声望6.9k 粉丝

自信自律, 终身学习, 创业者