最近老板安排了一个开发浏览器插件的项目,总结一下用到的东西。

一、框架

同事搭的一个vue版框架

https://github.com/kiccer/vue-crx-template

整体目录结构
在这里插入图片描述

二、各页面通讯

1.content与background

1.1content发送
/*
    content向background发消息
    id: 消息唯一id
    command: (必填)命令
    parameter: 携带的参数
*/
export const contentToBackground = (id, command, parameter = {}) => {
    const sendData = {
        from: 'plugin',
        id,
        command,
        parameter
    }
    chrome.runtime.sendMessage(sendData, function (response) {
        log(command + ', response', response)
    })
}

这里是我封装了一下,:主要用到的就是chrome.runtime.sendMessage方法

1.2background接收
// 监听来自content的消息
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    // log(' 接收消息:', request)
    if (request.from === 'plugin') {
        if (request.command === 'eventA') {
            eventA(request.parameter)
        } else if (request.command === 'eventB') {
            eventB(request.parameter)
        }
    }
})
1.3background发送
// 给content发送消息
// id: 消息唯一id
// command: 请求的命令
// status: 消息状态
// data: 数据
function sendMessageToContent (id, command, status = true, data) {
    const postData = {
        from: 'plugin',
        id: id,
        command: command,
        status: status,
        data: data
    }
    log('postData', postData)
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, postData, function (response) {
            log('response: ', response)
        })
    })
}
1.4content接收
chrome.extension.onMessage.addListener(
     function (request, sender, sendResponse) {
         log('接收 request: ', request)
         if (request.from && request.from === 'plugin') {
             switch (request.command) {
             case 'eventA':
                 that.eventA()
                 break
             case 'eventB':
                 that.eventB()
                 break
             }
         }
     }
 )

2.content与iframe

需求需要用到与iframe通讯

为了方便调用,写成了promise形式
将resolve放在promiseMap对象中,等消息返回后再通过id来获取相应的resolve

2.1iframe发送
// command 命令
// parameter 参数
const request = (command, parameter) => {
    return new Promise((resolve, reject) => {
        const request = {
            id: util.getUid(),
            type: 'request',
            from: 'plugin',
            command: command,
            parameter: parameter
        }
        promiseMap[request.id] = {
            resolve,
            reject
        }
        log('发送 request:', request)
        window.parent.postMessage(request, '*')
    })
}
2.2content接收
window.addEventListener('message', function (e) {
     const res = e.data
     if (res.from === 'plugin') {
         log('接收 res', res)
         switch (res.command) {
         case 'eventA':
             that.eventA(res.id, res.command)
             break
         case 'eventB':
             that.eventB(res.id, res.command)
             break
         }
     }
 }, false)
2.3content 发送
// id: 消息唯一id
// command: 请求的命令
// status: 消息状态
// data: 数据
sendMessageToIframe (id, command, status = true, data) {
    if (this.$refs.iframe) {
        const postData = {
            from: 'plugin',
            id: id,
            command: command,
            status: status,
            data: data
        }
        log('发送 message postData', postData)
        this.$refs.iframe.contentWindow.postMessage(postData, '*')
    }
},
2.4iframe接收
window.addEventListener('message', function (e) {
    if (e.data.from === 'plugin') {
        const res = e.data
        log('接收 postMessage res: ', res)
        const promise = promiseMap[res.id]
        if (promise) {
            if (res.status) {
                promise.resolve(res.data)
            } else {
                promise.reject(res.data)
            }
        }
        if (res.type === 'request') {
            delete promiseMap[res.id]
        }
    }
}, false)

3.content与popup

和content与background通讯方式相同

三、部分Api

官方API文档点这里

1.切换至某窗口

chrome.tabs.highlight

chrome.tabs.highlight({ tabs: tabIndex }, (res) => {
    log('切换到指定标签页 res: ', res)
})

一般与下面这个 查询窗口信息api(chrome.tabs.query)放在一起用

2.查询某窗口信息

chrome.tabs.query
封装成了查看某窗口是否打开的方法
需要一个uri,比如 https://www.baidu.com/

export const checkTab = (targetUrl) => {
    return new Promise((resolve, reject) => {
        chrome.tabs.query({}, tabs => {
            log('当前浏览器打开的页面列表: ', tabs)
            let isExist = false
            let tabIndex = ''
            let highlighted = false
            for (let i = 0; i < tabs.length; i++) {
                const tab = tabs[i]
                if (tab.url && tab.url.indexOf(targetUrl) !== -1) {
                    isExist = true
                    tabIndex = tab.index
                    highlighted = tab.highlighted
                }
            }
            if (isExist) {
                // chrome.tabs.highlight({ tabs: tabIndex }, (res) => {
                //     log('highlight res: ', res)
                // })
                resolve({ isExist, tabIndex, highlighted })
            } else {
                resolve({ isExist })
            }
        })
    })
}

3.存储

chrome.storage.local.set({ userInfo: data }, function () {
   log('存储成功')
})


第一个参数是一个列表,可以是多个一起提取,变量名会以key的形式在result中

chrome.storage.local.get(['userInfo'], function (result) {
	log('result: ', result)
})

chrome.storage.sync 方法与以上用法一样,而且可以与用户信息同步

暂时写到这里…

Logo

前往低代码交流专区

更多推荐