Chrome 扩展开发:分页和 iframe中的内容(三)

Chrome 扩展开发:分页和 iframe中的内容(三)

本文介绍了在扩展上,分页的实现,以及如何获取 iframe 中的内容。这是《Chrome 扩展开发》系列的第三篇,也是最后一篇。

一、 分页

扩展所在的页面是一个列表,会有一些商品信息。在点击分页时,在每个商品旁插入一些信息。列表页在加载下一页列表时,并不会触发 DOMContentLoaded 事件。

目前,我的实现是在点击时触发一个函数。函数先获取页面的一个特殊信息。在 setInterval 中隔一段时间,获取一遍信息。比对这两次信息,如果相同,再重复上述操作。使用 Lodash 的 isEqual 进行数据比较。不同的话,就说明页面的分页操作已经完成,这个时候就可以进行你想要的操作了。例如,插入信息或者发起请求。代码如下:

/**
 * 监听获取到的信息,发生改变时调用回调
 * @param getDataFunc 获取的信息函数
 * @param method setInterval 何时终止:'same' 数据相同时终止 ; 'diff' 数据不同时终止
 * @param callback 要运行的回调
var monitorDomChange = function (getDataFunc, method='same', callback) {
    var old = getDataFunc()
    var load = setInterval(function () {
        var newValue = getDataFunc()
        var equal = _.isEqual(old, newValue)
        var isInterval = (method === 'same') ? equal : !equal
        if (isInterval) {
            clearInterval(load)
            callback()
    }, 500)

那么,令人头疼的分页问题解决了?未必。在点击部分页码时,会加载出新的页码。但是新的页面没有绑定点击事件。例如,一开始加载了 12345、10。点击按钮 5 后,新加载出页码 6、7。在点击 6 、7 时没有绑定事件,查询的结果没有展示。

解决方法如下:在每次点击的时候,执行完相应操作后,递归调用当前事件。元素绑定点击事件时,需要先进行一次解绑点击事件,避免事件多次绑定。

var paginationAction = function () {
    var pageNumEle = $('.pagination-item')
    pageNumEle.each(function () {
        $(this).unbind("click").bind("click",function(){
            monitorDomChange(getSpecialData, 'diff', function () {
                // 生成容器元素
               insertEleFunc()
                paginationAction()

二、 iframe 中的内容

这个问题比较小众,一般而言,应避免使用 iframe。我先来普及一下 iframe 的特性:每一次插入 iframe后都是一个新的 window 对象。如果使用Lodash 的 once 让某个函数只执行一次,显然是不会生效的。因为每一个新的 window 下都运行一次。这恰恰不是我们所期待的。另外,在扩展开发过程中,使用 iframe 时 localStorage 和 sessionStorage 都有同源限制。 只能使用 chrome storage 传参数。

前置知识说完了,考虑一个业务场景,在当前页面获取获取 iframe 中的内容。例如用户名称。在页面嵌入 iframe,将网页链接放入。本来想直接通过 contentDocument 获取元素的值。但是插入的页面 iframe 和 parent 页面不同源。限制了我使用 iframe 的 DOM.

于是,我使用 window.postMessage 方法,的确建立了通信。但是 ifrmae 的 dom 我还是无法获取。

//iframe
iframe.onload = function() {
    window.parent.postMessage('test', '*');
// parent.html
var getInfoFromIframe = function () {
    window.addEventListener('message', function (e) {
        log('e', e.data)