不能立即在 pop-up window 中 'press' 刚创建的按钮。我必须关闭 pop-up 然后再打开它 (chrome-extension pop-up)

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)

欣赏,可略过

我在这里 post 读到了这篇很棒的文章:How do I return the response from an asynchronous call?。多亏了这里令人惊叹的社区,我在这个项目上取得了很大进展,但还有最后一个错误。

程序应该如何运行

我有一个程序,它使用 chrome-extension (browser-action)。当用户点击一个图标时he/she可以添加当前网站的link,一次删除所有的link,或者只删除一个带有[=的link link 标题旁边的 70=] 按钮。

密码

来自popup.js,问题出在这些函数的'flow'

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

错误

每当我在 popup-window 中按下 'add link' 时,就会显示 link 和 'X' 按钮。但是,当我按下该按钮时,它不会立即起作用。我首先必须关闭 popup-window,再次打开它,然后按 'X' 按钮才有效。我知道我的异步调用顺序有问题,但我无法确定。

编辑

我已经添加了 Andrew 的答案,但似乎存在以下问题:每次我尝试删除 last link 时,它工作正常,没有问题.只有当我有一个 link before 最后一个(或前 2 个位置甚至第一个 link)并尝试删除那个 link通过 'X' 按钮,它会删除所有 links 下 link 包括 link待删除。请看这张照片:

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

之后:在我点击那个按钮之后:https://i.stack.imgur.com/cafqr.png

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

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

 list.removeChild(item);

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

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();
}