【问题标题】:Cannot 'press' a just created button inside a pop-up window immediately. I have to close the pop-up and then open it again (chrome-extension pop-up)无法立即在弹出窗口中“按下”刚刚创建的按钮。我必须关闭弹出窗口,然后再次打开它(chrome-extension 弹出窗口)
【发布时间】:2016-12-28 11:29:55
【问题描述】:

欣赏,可以跳过

我在这里阅读了这篇很棒的帖子:How do I return the response from an asynchronous call?。感谢这里令人惊叹的社区,我在这个项目上已经走了很远,但只有最后一个错误。

程序应该如何运行

我有一个程序,它使用 chrome 扩展(浏览器操作)。当用户点击一个图标时,他/她可以添加当前网站的链接,一次删除所有链接,或者只删除一个链接标题旁边带有“X”按钮的链接。

代码

这是来自 popup.js,问题在于这些函数的“流程”。

document.addEventListener('DOMContentLoaded', function() {
    restore();
    document.getElementById('add').addEventListener('click', fetchUrl);
    document.getElementById('clear').addEventListener('click', clearAll);
  });

function restore() {
    // get the tab link and title
    chrome.storage.local.get({urlList:[], titleList:[]}, function(data) {
        urlList = data.urlList;
        titleList = data.titleList;
     
        // add the titles and url's to the DOM
        for (var i = 0, n = urlList.length; i < n; i++) {
            addToDom(urlList[i], titleList[i]);
        }
        
        // create event listeners for all the 'X' buttons next to list items
        // after the 'addToDom' function has been executed
        var allButtons = document.getElementsByClassName('buttons');
        for (var j = 0, k = allButtons.length; j < k; j++) {
            listenJ(j);
        } 
        function listenJ(j) {
            allButtons[j].addEventListener('click', () => removeMe(j));
        }   
    }); 
}

function removeMe(j) {
    // remove it from the DOM
    var items = document.getElementsByClassName('items');
    var list = document.getElementById('list');
    // the specific URL to delete
    var item = items[j];
    list.removeChild(item);
    
    // return the DOM to original state
    if (items.length === 0) {
    document.getElementById('list').innerHTML = '';
    document.getElementById('div').innerHTML = '<h3>No content yet! Click "add link" to add the link of the current website!</h3>';
    }
    
    // remove it from chrome-storage
    chrome.storage.local.get({urlList:[], titleList:[]}, function(data) {
        urlList = data.urlList;
        titleList = data.titleList;
        urlList.splice(j, 1);
        titleList.splice(j, 1);

        // update chrome storage
        saveList();
    }); 
}

function addToDom(url, title){
    // change the (greeting) text message
    document.getElementById("div").innerHTML = "<h2 id='title'>Saved Pages</h2>";
  
    // Build the new DOM elements programmatically
    var newLine = document.createElement('li');
    var newLink = document.createElement('a');
    var button = document.createElement('button');
    newLink.textContent = title;
    newLine.appendChild(button);
    button.setAttribute('class', 'buttons');
    button.textContent = 'delete';
    newLine.setAttribute('class', 'items');
    newLink.setAttribute('href', url);
    newLink.setAttribute('target', '_blank');   // opens link in new tab
    newLink.setAttribute('tabindex', -1);       // remove focus from links in popup-window
    newLink.setAttribute('id', 'item');
    newLine.appendChild(newLink);
    document.getElementById('list').appendChild(newLine);
}

更多信息:

popup.html:gist.github.com/kobrajunior/1c26691734c19391c62dc336ed2e1791

manifest.json:gist.github.com/kobrajunior/78acda830c2d1c384333542422f1494d

错误

每当我在弹出窗口中按“添加链接”时,都会显示链接和“X”按钮。但是,当我按下该按钮时,它不会立即起作用。我首先必须关闭弹出窗口,再次打开它,然后按“X”按钮即可。我知道我拥有的异步调用的顺序有问题,但我不能指望它。

编辑

我已经添加了 Andrew 的答案,但似乎存在以下问题:每次我尝试删除 last 链接时,它都可以正常工作而没有问题。只有当我最后一个链接之前(或在第一个链接之前或什至第一个链接之前有 2 个位置)并尝试通过“X”按钮删除该链接时,它才会删除所有链接 已删除的链接下包括要删除的链接。请看这张照片:

之前:我还没有点击那个按钮,但我即将点击:https://i.stack.imgur.com/IFZc6.png

之后:点击该按钮后:https://i.stack.imgur.com/cafqr.png

此外,每当我尝试删除一个链接时,调试器都会给我这个错误:https://i.stack.imgur.com/nStFr.png

该错误的位置在我的 removeMe 函数和这个特定代码中:

 list.removeChild(item);

【问题讨论】:

  • 不要链接到代码。向我们展示一个重现问题的 mininal 代码示例。还显示您使用调试器的尝试。
  • 好的,先生,对不起。我已经粘贴了问题所在的所有代码,并添加了调试它的尝试。谢谢你的建议。
  • google如何调试弹窗,先尝试调试一下。
  • @Zig Mandel 如果我不理解你,我很抱歉,但我不知道如何使用“检查弹出窗口”调试这个特定问题。它与此处描述的不同:developer.chrome.com/extensions/tut_debugging。问题是该按钮第一次根本没有做任何事情,但第二次弹出窗口打开它时,我不知道如何在那种特定情况下使用调试器。我已经用图片编辑了帖子,以确定这是您的意思的调试器?
  • 您调试代码在哪里(.js),我从您的图片中可以看出不在 pupup.html 中,但可能在 popup.js 中。

标签: javascript google-chrome asynchronous google-chrome-extension popupwindow


【解决方案1】:

我认为这里的问题是您正在创建一个元素,如下所示:

function addToDom(url, title){
    // change the (greeting) text message
    document.getElementById("div").innerHTML = "<h2 id='title'>Saved Pages</h2>";

    // Build the new DOM elements programmatically
    var newLine = document.createElement('li');
    var newLink = document.createElement('a');
    var button = document.createElement('button');
    newLink.textContent = title;
    newLine.appendChild(button);
    button.setAttribute('class', 'buttons');
    button.textContent = 'delete';
    newLine.setAttribute('class', 'items');
    newLink.setAttribute('href', url);
    newLink.setAttribute('target', '_blank');   // opens link in new tab
    newLink.setAttribute('tabindex', -1);       // remove focus from links in popup-window
    newLink.setAttribute('id', 'item');
    newLine.appendChild(newLink);
    document.getElementById('list').appendChild(newLine);
}

最后一行创建一个子元素并将其附加到页面。但是,由于这个子元素是在附加了事件绑定之后创建的,因此没有附加到这个特定元素的事件绑定。

function restore() {
    // get the tab link and title
    chrome.storage.local.get({urlList:[], titleList:[]}, function(data) {
        urlList = data.urlList;
        titleList = data.titleList;

        // add the titles and url's to the DOM
        for (var i = 0, n = urlList.length; i < n; i++) {
            addToDom(urlList[i], titleList[i]);
        }

        // create event listeners for all the 'X' buttons next to list items
        // after the 'addToDom' function has been executed
        var allButtons = document.getElementsByClassName('buttons');
        for (var j = 0, k = allButtons.length; j < k; j++) {
            listenJ(j);
        } 
        function listenJ(j) {
            allButtons[j].addEventListener('click', () => removeMe(j));
        }   
    }); 
}

想象一下,如果有 8 个人参加吃馅饼比赛。那些人一开始得到馅饼,可以坐下来吃馅饼。

如果一个人迟到了。他没有馅饼,因为它们已经分发出去了。所以他无法参加比赛。

上面的代码就是这样做的。它会在稍后出现的这个人拥有一个之前分配事件(饼图)。

所以只需将函数移出即可。

function createButtonEvents() {
    // create event listeners for all the 'X' buttons next to list items
    // after the 'addToDom' function has been executed
    var allButtons = document.getElementsByClassName('buttons');
    for (var j = 0, k = allButtons.length; j < k; j++) {
        listenJ(j);
    } 
    function listenJ(j) {
        allButtons[j].addEventListener('click', () => removeMe(j));
    }   
}

function restore() {
    // get the tab link and title
    chrome.storage.local.get({urlList:[], titleList:[]}, function(data) {
        urlList = data.urlList;
        titleList = data.titleList;

        // add the titles and url's to the DOM
        for (var i = 0, n = urlList.length; i < n; i++) {
            addToDom(urlList[i], titleList[i]);
        }
        createButtonEvents();
    }); 
}

然后在创建按钮后在我们的创建函数中调用它。

function addToDom(url, title){
    // change the (greeting) text message
    document.getElementById("div").innerHTML = "<h2 id='title'>Saved Pages</h2>";

    // Build the new DOM elements programmatically
    var newLine = document.createElement('li');
    var newLink = document.createElement('a');
    var button = document.createElement('button');
    newLink.textContent = title;
    newLine.appendChild(button);
    button.setAttribute('class', 'buttons');
    button.textContent = 'delete';
    newLine.setAttribute('class', 'items');
    newLink.setAttribute('href', url);
    newLink.setAttribute('target', '_blank');   // opens link in new tab
    newLink.setAttribute('tabindex', -1);       // remove focus from links in popup-window
    newLink.setAttribute('id', 'item');
    newLine.appendChild(newLink);
    document.getElementById('list').appendChild(newLine);
    createButtonEvents();
}

【讨论】:

  • 我认为我有问题但没有解决方案:只有当我尝试执行此代码时,弹出窗口才会反应奇怪:list.removeChild(items[j]);其中'j'可以是任何数字,调试器对我大喊大叫。对于所有大于 '0' 的数字,它给了我上面提到的未捕获的 typeError 但它有效。如果 j === 0 则调试器控制台抛出 same 错误并删除所有链接....
  • @Kobrajunior 你应该看看帮助吸血鬼这个词的含义,并将它与你目前正在做的事情进行比较。最初的问题是关于为什么您的事件没有正确绑定,而不是为什么您的代码无法正常工作。
  • @Kobrajunior 老实说,在重新阅读之后,我不能 100% 确定您是否处于 HV 领域。无论哪种方式,我建议在按钮元素所在的容器上设置一个事件,并使用event.target 删除条目。示例:jsbin.com/vivovunusu/edit?html,js,output 文档条目:developer.mozilla.org/en-US/docs/Web/API/Event/target
猜你喜欢
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
  • 1970-01-01
  • 2012-01-26
相关资源
最近更新 更多