美文网首页
chrome扩展程序初体验

chrome扩展程序初体验

作者: cythia_yyy | 来源:发表于2019-05-30 09:28 被阅读0次

    常被称为chrome插件,虽然名称定语为chrome,但是chrome扩展程序除了在chrome浏览器上使用,理论上还可以运行在wekit内核的浏览器上(毕竟chrome已经和webkit分道扬镳开始走Blink内核了)

    chrome扩展主要是增强浏览器的功能,能定制个人专属的浏览器不是很有意思😏

    用chrome扩展可以==对页面原有DOM进行修改==,比如本例是对大搜车全体开发人员的语雀个人中心进行扩展,在原页面的基础上将开发人员的日常动态集中在一个页面中,包括gitlab的git热力图。直接重写整个页面的成本过大,所以就用chrome扩展对原页面进行二次修改,并能避免第三方接口跨域的问题。

    上述情景包括Chrome扩展的开发,嵌入的iframe页面的开发,下面主要写的是chrome开发总结,适合chrome开发新手。

    入门须知:

    chrome扩展程序的主要组成:

    • manifest.json // 说明整个程序的配置,必选 (具体各配置项参考官方配置API文档
    • background.js // 后台脚本,默认持续运行在后台的脚本
    • content.js // 内容脚本,注入到匹配吻合页面的脚本
    • popup.html // 扩展图标点击查看的视图窗

    脚本类型

    注入到原网页上下文的脚本

    与原页面自带脚本同等的脚本,可以访问原页面脚本中的所有变量,这种脚本只能使用网页的通用API,无法使用chrome扩展提供的API,使用时==需要在mainfest.js中配置web-accessible-resources==,表明扩展程序的某些脚本可以从网页访问

    "web_accessible_resources": [
        "js/sideTag.js"
    ]
    


    重新载入,不属于扩展程序的脚本

    content脚本

    注入到匹配的当前页面中的脚本,但是并不能完成融入到当前页面的脚本中,而是运行在一个被隔离的环境中,能共享当前页面的DOM对象,但==无法获取当前页面的全部数据==,例如当前页面脚本中的变量数据,在这种脚本中可以使用部分chrome扩展的API,可以用来解决跨域问题(后文详解),在mainfest中配置content

    "content_scripts": [{
        "matches": ["*://souche.yuque.com/*"],
        "js": ["modifyDom.js"],
        "run_at": "document_end"
    }]
    

    重新载入,不完全属于扩展程序的脚本

    background脚本

    运行在后台的脚本,与当前浏览页面无关,但是这类脚本==可以保持持续运行或者活动时运行==,持续运行在浏览器页面打开到关闭的时间里,活动状态运行为一种非持续运行后台脚本,可以在不活动状态释放占用的资源,提高性能;后台脚本可以使用全部的chrome扩展API,在mainfest中配置background

    "background": {
        "scripts": ["background.js"],
        "persistent": false 
        // true表明持续运行,false非持续运行
    }
    


    在非持续运行时,每次页面活动会触发重新载入,持续运行时加载一次,完全属于扩展程序的脚本

    popup脚本

    也就是我们常见的在点击扩展图标时弹出的视图窗口,它和background脚本一样可以使用全部的chrome扩展API,==一般会用来用户授权==,但是最好在用户授权之后将授权信息保存在本地,不然每次打开都需要用户授权就很不友好了(这次没实现popup,只能说说我所了解的),在mainfest中配置popup

    "browser_action" : {
        "default_title" : "搜车KM",
        "default_popup" : "popup.html",
        "default_icon" : {
          "16" : "KM.png"
        }
    }
    

    用户每次点击图标都会重新载入脚本,完全属于扩展程序的脚本

    再往下分析一下实践中一定会碰到的通信和跨域问题,毕竟这些坑都踩了--

    通信问题

    注入脚本与原页面脚本:

    可以从注入脚本中获取到原页面脚本的变量,通过window.addEventListener和 window.postMessage来实现,例如获取window对象中的特殊属性,🌰

    // 注入脚本 sideTag.js
    window.postMessage({ "sLogin": window.appData.me.login }, '*');
    // 内容脚本 modifyDom.js
    var sLogin = '';
    window.addEventListener("message", function (event){
    if (event.data.sLogin) {
            sLogin = event.data.sLogin
        }
    }, false);
    

    之前为了获取原页面的window.appData数据,用了一种很ZZ的方法——模版字符串,能实现,但是代码看起来真的累啊。。。来个对比吧 -_-|

    // 内容脚本使用模版字符串code


    image

    // 内容脚本引用code


    image
    // 注入脚本code
    image

    PS: 同一个扩展程序的不同注入脚本是运行在同一个上下文的,注意变量不要重复声明

    内容脚本与“完全属于扩展程序脚本”的通信:

    这两者之前是可以互通消息的,==内容脚本可以调用chrome.runtime的API==,后者可以调用chrome.*的全部API,只是两者作为发送方时发送的方式不一样

    // 内容脚本 modifyDom.js
    chrome.runtime.sendMessage(
        {
            type: 'get',
            url: 'https://skm.souche.com/user/' + urlParam // 需要请求的url
        },
        response => {
            // ...
        }
    )
    ​
    // 后台脚本 background.js
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
        // ...
      });
    });
    

    接收方的方法一致,🌰

    // 后台脚本 background.js
    chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
      if (request.type == 'get') {
        fetch(request.url)
          .then(response => {
            if (response.status === 200) return response.text()
            else if (response.status === 401) {
              return Promise.resolve(response.status)
            }
          })
          .then(text => {
            sendResponse(text)
          })
          .catch(error => console.error('error', error))
        return true // 异步
      }
    })
    

    “完全属于扩展程序脚本”之间的通信:

    他们之间函数是可以==直接互相访问==的,并且可以互相访问对方的DOM元素;所以他们之间事实上不存在什么复杂的通信

    跨域问题

    跨域感觉是使用chrome扩展的大收益,毕竟有些第三方API不允许服务端直接跨域请求啊。。。

    在扩展脚本中使用XHR发起跨域请求,第三方域名需要在mainfest的permissions中配置一下

    "permissions": [
        "*://souche.yuque.com/*",
        "*://skm.souche.com/*",
        "*://git.souche-inc.com/*",
        "*://f2e-assets.souche.com/*"
    ]
    

    BUT,前不久chrome扩展已经不支持内容脚本中xhr的跨域请求了,开发中的我不得已换了跨域的方法,也就是前面通信中提到的chrome.runtime的调用,==在后台脚本中处理内容脚本的外部服务器请求==,(此处自行回看上文代码)再将处理后的数据发送给内容脚本,前端同学生活不易啊,说不定一觉起来你的代码就跑不动了。。。

    emmm... 给大家看一下前后对比图吧😅


    image
    image

    第一次写chrome扩展,总结的肯定不全面,大佬们多多指导。

    相关文章

      网友评论

          本文标题:chrome扩展程序初体验

          本文链接:https://www.haomeiwen.com/subject/lgaptctx.html