crm开发定制chrome插件开发入门-保姆级攻略

文章目录

crm开发定制这里先插播一条消息

Manifest version 2 is deprecated, and support will be removed in 2023. See https://developer.chrome.com/blog/mv2-transition/ for more details.

MV2版本的在2023crm开发定制年停止支持

chromecrm开发定制插件应该包含哪些文件及文件夹

D:.│  manifest.json│├─html│      index.html│├─images│      icon-128.png│      icon-16.png│├─scripts│      background.js│├─styles│      main.css│└─_locales    ├─en    │      messages.json    │    └─zh_CN            messages.json
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  1. html:存放html页面
  2. images:crm开发定制存放插件图标
  3. scripts:存放js文件
  4. styles:存放样式
  5. _locales:crm开发定制存放多语言文件
  6. manifest.json:crm开发定制用来配置所有和插件相关的配置,作为chrome入口文件,crm开发定制必须放在根目录(必须存在

分析

  1. crm开发定制目录结构像一个web网页,crm开发定制他的本质上就是一个网站类应用,是一个webapp
  2. crm开发定制相对于普通的webapp,crm开发定制还可以调用更多的浏览器层面的api,包括数钱、历史记录、crm开发定制网络请求拦截、crm开发定制截获用户输入等等

crm开发定制重要配置说明

manifest.json

crm开发定制额外的配置参见

{    "manifest_version": 3, // crm开发定制清单版本号,建议使用 版本 3,版本 1和2 是旧的,已弃用,crm开发定制不建议使用    "name": "first-test-plugin", // 插件名称    "version": "0.0.1", // 插件版本    "description": "这里是第一个测试插件", // 描述,可写可不写    "icons":    {        "16": "images/custom/16x16.png",        "48": "images/custom/48x48.png",        "128": "images/custom/128x128.png"    },    // !!!browser_action和page_action只能添加一个    "browser_action": //浏览器级别行为,所有页面均生效    {        "default_icon": "images/custom/16x16.png", // 图标的图片        "default_title": "Hello lanfengqiuqian", // 鼠标移到图标显示的文字        "default_popup": "html/popup.html" // 单击图标后弹窗页面    },    "page_action": //页面级别的行为,只在特定页面下生效    {        "default_icon":        {            "24": "images/custom/24x24.png",            "38": "images/custom/38x38.png"        },        "default_popup": "html/popup.html",        "default_title": "Hello lanfengqiuqian"    },    "author": "lanfengqiuqian", // 可选填写    "automation": false, // 是否开启自动化    "background": // 背景页的脚本路径,一般为插件目录的相对地址    {        "scripts": [            "scripts/background.js",            "scripts/devtools-page.js"        ]    },    "devtools_page": "html/devtools-page.html", // 在开发工具中的页面    "content_scripts": [ // 内容脚本一般植入会被植入到页面中, 并且可以控制页面中的dom        {            "js": ["js/else-insert.js"], // 这里面的数组都是可以放多个的            "css": ["css/else-insert.css"],            "matches": ["<all_urls>"] // 被植入到页面,只在这些站点下 content_scripts会运行        }    ],    "permissions": [ // 安装的时候提示㤇的权限        "cookies", // 使用cookies        "webRequest", // 使用web请求        "http://*", // 可以通过executeScript或者insertCSS访问的网站地址。如: https://*.google.com/        "management", //        "storage", // 使用本地存储        "tabs", // 操作标签        "contextMenus" //右键菜单    ]    "default_locale ": "zh_CN" //默认语言(比如"zh_CN")}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

开始手撸一个插件

准备工作

创建一个文件夹,如我的叫 extensions (之后说的根目录都是指这个目录下)
文件夹下创建一个 img 目录,用于存放一些logo之类的图片

放入一张图片,如logo.png

文件夹下创建一个 html 目录,用于存放html文件
文件夹下创建一个 js 目录,用于存放js文件

这里如果你想先放一个jquery文件用于加载也是可以的,我后面为了方便使用的是script引入

文件夹下创建一个 css 目录,用于存放css文件

文件夹根目录下创建一个 manifest.json 文件

{    "manifest_version":3,	"name":"这是插件名称",	"version":"0.0.1",	"description":"这是插件描述",    "action":{		"default_title":"这是鼠标移上去时提示文字",        "default_popup":"html/popup.html"	},	"icons":{		"16":"img/logo.png",		"32":"img/logo.png",		"48":"img/logo.png",		"128":"img/logo.png"	}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

然后chrome扩展程序【加载已解压的扩展程序】选择刚才创建的extensions目录

效果如下

pupup部分

  1. /html新建一个popup.html文件,然后在manifest.json中的action配置popup的路径

    "action":{    "default_title":"这是鼠标移上去时提示文字",    "default_popup":"html/popup.html"}
    • 1
    • 2
    • 3
    • 4
    <!DOCTYPE html><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    <link rel="stylesheet" type="text/css" href="../css/popup.css" /></head><body>    <div class="btn">        测试<input id="TEST" class="checkbtn" type="checkbox" />    </div></body><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script><script src="../js/popup.js"></script></html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  2. 在css和js目录中分别新建popup.csspopup.js文件

    /* popup.css */.btn{    width: 100px;    height: 30px;    font-size: large;}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    //popup.js$(".checkbtn").click(function(){    alert($(this).attr('id'));});
    • 1
    • 2
    • 3
    • 4
  3. 然后重载扩展程序

    点击插件,效果如下

  4. 待解决问题

    每次勾选的checkbox都会被还原,所以接下来需要做一个本地存储来保存的改变

background部分

  1. manifest.json中加入service_worker的配置路径和permissions

    "background":{    "service_worker":"background.js"},"permissions":["storage"]
    • 1
    • 2
    • 3
    • 4

    注意:service_worker说明

    1. 这个是一直伴随插件运行的后台脚本
    2. 没有前端页面,不支持dom,所以不能引入jQuery和其他js
    3. 所有需要保持运行的脚本都需要直接卸载background.js文件里
    4. 同样也不支持XMLHttpRequest,所以需要使用fetch来替代xhr请求
    5. 一定要放在根目录(扩展文件根目录,不是电脑磁盘根目录),否则在使用的时候会出现service worker(无效)提示
    6. 可以在扩展程序=>查看视图点击弹出的控制台查看输出
  2. 在根目录写background.js文件

    //background.jschrome.runtime.onInstalled.addListener(() => {    DBdata("clear");//清除插件保存的本地数据});//插件用的数据都存储在storage.local中function DBdata(mode,callback,data){//操作本地存储的函数    if(mode=="set"){//保存本地数据        console.log('set-LocalDB');        chrome.storage.local.set({LocalDB: data});    }else if(mode=="get"){//获取        chrome.storage.local.get('LocalDB', function(response) {            typeof callback == 'function' ? callback(response) : null;        });    }else if(mode=="clear"){//清空        chrome.storage.local.clear();    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  3. 打开popup.js,把原来的点击事件删掉,在其中加入初始化和连接service_worker的脚本

    //popup.jswindow.bgCommunicationPort = chrome.runtime.connect();//初始化bgCommunicationPort$(".checkbtn").click(function(){    bgCommunicationPort.postMessage({//发送到bg,键值可以自由设置        Direct : $(this).attr('id'),//目标        Content : '测试内容',//内容        step : 0//步骤    });});$(document).ready(function(){//打开popup时触发,读取之前存储的参数    bgCommunicationPort.postMessage({fromPopup:'getDB'});//向background发送消息    bgCommunicationPort.onMessage.addListener(function(receivedPortMsg) {//监听background        console.log(receivedPortMsg);//这是background发来的内容        if(receivedPortMsg&&receivedPortMsg.Direct){            $(".checkbtn").prop({'checked': false});//初始化按钮            $("#"+receivedPortMsg.Direct).prop({'checked': true});        }    });});
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  4. 打开background.js,在其中加入监听popup的脚本(这里不要删除原来的哦,加到后面即可)

    //background.jschrome.runtime.onConnect.addListener(function(port) {//接收到popup    port.onMessage.addListener(function(receivedMsg) {//监听popup发来的内容receivedMsg        if(receivedMsg.fromPopup&&receivedMsg.fromPopup=='getDB'){//如果接收到了getDB,这里读取数据并返回相当于初始化popup页面            DBdata('get',function(res){                port.postMessage(res.LocalDB);//发送到popup            });        }else{//如果不是,则说明是收到来自popup手动点击设置的数据,存入以用于popup打开时展示            DBdata('set','',receivedMsg)        }    })});
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  5. 重载插件

    1. 这个时候会发现有两个报错

      发现是用script引入的jquery

      那么就改为文件引入呗

      1. 在js目录下新建jquery.js

        到去下载production版本的js

        然后把他的内容放到jquery.js

      2. 修改popup.html文件中的jquery引入

        <script src="../js/jquery.js"></script>
        • 1
    2. 重载插件,发现报错都好了

  6. 测试

    每次重置勾选的问题已经好了

content部分

content可以注入到浏览的网页,操作dom,所以就可以实现很多功能了

  1. manifest.json中加入content的配置
"content_scripts":[{    "js":["js/jquery.js","js/content.js"],/*content可以随意引入js,因为其内容会在浏览的网页上直接运行*/    "matches":["*://localhost/*"],/*在哪些网页上运行*/    "run_at":"document_end"/* 在页面加载完成时运行 */}]
  • 1
  • 2
  • 3
  • 4
  • 5

注意这里现在只是匹配的localhost

  1. 新建js/content.js,在content.js中写入

    //content.js   manifest匹配地址的页面在刷新时会直接执行这里的代码chrome.runtime.sendMessage(chrome.runtime.id, {//当页面刷新时发送到bg    fromContent: 'getDB'});chrome.runtime.onMessage.addListener(function(senderRequest, sender, sendResponse) {//接收到bg    console.log('demo已运行');    var LocalDB=senderRequest.LocalDB;    console.log(LocalDB);    switch(LocalDB.Direct){        case 'TEST':            console.log(123123);            break;        default:            break;    }    // 不写会报错 Unchecked runtime.lastError: The message port closed before a response was received.    sendResponse('这里是content返回值');});
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  2. 然后background.js中加入监听content的代码

    //background.jschrome.runtime.onMessage.addListener(function (senderRequest, sender, sendResponse) {//接收到content    // 不写会报错 Unchecked runtime.lastError: The message port closed before a response was received.    sendResponse({ msg: '接收到content' });    console.log(senderRequest);    if (senderRequest.fromContent && senderRequest.fromContent == 'getDB') {//接收到fromContent:getDB        DBdata('get', function (res) {//从本地取数据            if (res.LocalDB) {                var LocalDB = res.LocalDB;                switch (LocalDB.Direct) {                    //如果是存入的TEST按钮                    case 'TEST':                        chrome.tabs.query({                            active: true,                            currentWindow: true                        }, function (tabs) {                            chrome.tabs.sendMessage(tabs[0].id, { LocalDB: LocalDB }, function (res) {                                console.log('接收content的回调', res);                            });//发送到content		                        });                        break;                    default:                        break;                }            }        });    }});
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    这里注意sendResponse这个方法,有的没有在回调中加上这个参数,导致找不到

  3. 重载插件

  4. 代码执行顺序

    1. 插件初始化阶段

      1. 先执行插件初始化监听background.jsonInstalled,清除本地数据
    2. 手动点击插件图标,勾选插件

      1. 执行popue.jsready方法进行初始化
      2. 点击按钮触发click方法修改本地数据
    3. 网页刷新阶段

      1. 执行content.jssendMessage方法
      2. 执行background.jsonMessage方法
      3. 读取本地数据
      4. 根据本地数据决定是否sendMessagecontent

去广告插件

说明:这里对于广告的判断是类名为 .ad 的元素

如我的vue页面

<div>    <h2 class="ad">第一条广告</h2>    <h2 class="ad">第二条广告</h2>    <h2 class="ad">第三条广告</h2>    <h2>这里是正常的数据</h2></div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. popup.html中增加一个去广告按钮

    <div class="btn">    去广告<input id="removeAD" class="checkbtn" type="checkbox" /></div>
    • 1
    • 2
    • 3
  2. background.js中监听content部分增加对于removeAD的判断

    //如果是存入的removeAD按钮case 'removeAD':    chrome.tabs.query({active: true, currentWindow: true    }, function(tabs){        chrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB});//发送到content		    });    break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  3. content.js中监听background.js部分增加removeAD的判断

    case 'removeAD':    //隐藏含有ad的元素,来达到去广告的效果    $(".ad").hide();    break;
    • 1
    • 2
    • 3
    • 4
  4. 重载插件,勾选页面中的去广告,然后刷新页面,发现广告已经没有了

页面跳转和cookie

popup一样,content关闭之后也不会保存数据,当我们在A页面获取数据之后想要放到B页面上去,在content直接跳转是不会把获取到的数据传过去的,所以和background链接保存本地数据就派上用场了

案例:将csdn的cookie的UserNick显示在localhost:8081

  1. manifest.json中配置【域名脚本匹配】、【权限】和【主机权限】

    "permissions":["storage", "cookies"],"host_permissions": [	"*://www.csdn.net/*"],"content_scripts":[{	"js":["js/jquery.js","js/content.js"],	"matches":["*://localhost/*", "*://www.csdn.net/*"],	"run_at":"document_end"}]
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里千万要注意的是一定要能够匹配上的url,否则可能引起页面脚本无反应或者获取不到cookie

  2. popup.html中增加按钮

    <div class="btn">    csdn<input id="checkCsdnUserNick" class="checkbtn" type="checkbox" /></div>
    • 1
    • 2
    • 3
  3. background.js中增加对于csdn按钮的判断

    case 'checkCsdnUserNick':    console.log('LocalDB', LocalDB)    //popup设置数据的时候有个step属性,在多步操作的时候就开始发挥作用了    if(LocalDB.step==0){        LocalDB.step = 1;//将step设置成1        chrome.storage.local.set({            LocalDB: LocalDB//保存到本地数据        },function() {            chrome.tabs.update(null, {//将前台页面跳转到设置的url                // 这里的url不用带斜杠 /                url: 'https://www.csdn.net'            });        });    }else if(LocalDB.step==1){//因为csdn的地址我们也匹配了所以content在跳转到csdn之后会还是会回来,不同的是step已经是1了        chrome.cookies.get({//获取cookie            'url': "https://www.csdn.net",            'name': 'UserNick'        }, function(cookie) {            console.log('cookie', cookie);            console.log(cookie.value);//获取到的值            LocalDB.cookie=cookie.value;//把获取到的值放到本地数据的cookie属性里            LocalDB.step = 2;//将step设置成2            chrome.storage.local.set({//获取到cookie之后跳转到第二个页面                LocalDB: LocalDB//保存到本地数据            },function() {                chrome.tabs.update(null, {//将前台页面跳转到设置的url                    url: 'http://localhost:8081/'                });            });        });    }else if(LocalDB.step==2){//第二步        chrome.tabs.query({active: true, currentWindow: true}, function(tabs){//发送到content            chrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB});		        });    }    break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  4. content.js中增加对于csdn按钮的判断

    case 'checkCsdnUserNick':    if(LocalDB.step==2){        $("body").append('<h1>'+LocalDB.cookie+'</h1>');    }    break;
    • 1
    • 2
    • 3
    • 4
    • 5
  5. 重载插件,到csdn.net中开启插件,勾选csdn,然后刷新页面就能看到效果

    会获取csdn.netcookie中的昵称,然后跳转到localhost:8081,进行显示

过程中问题记录

  1. Unchecked runtime.lastError: The message port closed before a response was received.

    这个问题通常是由于其他插件引起的,注意排查,找到受影响的插件禁用即可

    大多数人是由于【迅雷】插件或者【油猴】插件引起的

  2. 扩展【移除】旁边多了一个【错误】的按钮

    1. 如果有错误提示,根据提示排查即可

    2. 如果没有错误提示,尝试将扩展移除重新加载即可

    3. 检查是否没有把sendMessagesendResponse配套使用

      每一个sendMessage都需要和sendResponse进行呼应

      也就是说,在每一个chrome.runtime.onMessage.addListener的回调函数中,需要使用sendResponse进行返回

      可以参见

  3. service worker看不到content.jsconsole.log

    原因是因为这个js是嵌入到页面中的,所以需要在使用的网页的控制台查看,而不是service worker

  4. 无法获取到cookie

    可能原因如下

    1. 没有授权host_permissions,控制台会报错Unchecked runtime.lastError: No host permissions for cookies at url: "https://www.csdn.net/".

      检查manifest.json中的此项配置,没有添加或者没有匹配上都会造成这个问题

    2. 检查chrome.cookies.get这个方法中的url是否完全正确

代码地址

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发