Firefox扩展弹窗无法加载自定义HTML表格问题求助
Firefox扩展弹窗无法加载表格数据的问题排查与解决方案
我正在开发一款Firefox扩展,功能是读取YouTube主页(https://www.youtube.com/)的可见视频数据,提取视频ID、标题、时长、频道名称及频道ID,最终在扩展弹窗里以自定义HTML表格展示。目前遇到的问题是:弹窗始终显示默认的“Loading...”文本,popup.js代码未触发,控制台看不到错误日志,无法生成目标表格。
相关代码
manifest.json
{ "manifest_version": 2, "name": "Ejemplo", "version": "1.0", "description": "Inspeccionar elementos de youtube.com.", "homepage_url": "https://github.com/mdn/webextensions-examples/tree/main/beastify", "icons": { "48": "icons/border-48.png" }, "applications": { "gecko": { "id": "manhunter45a45@example.com" } }, "permissions": [ "tabs", "activeTab", "storage", "background" ], "browser_action": { "default_icon": "icons/beasts-32.png", "default_title": "Obtain YouTube Info", "default_popup": "popup/results.html", "browser_style": true }, "content_scripts": [ { "matches": [ "https://*.youtube.com/" ], "js": [ "jquery-1.9.1.min.js", "Ejemplo.js", "/code/functions.js" ] } ], "background": { "scripts": [ "/code/popup.js" ] } }
results.html(弹窗页面)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <div id="allVideos"><i>Loading...</i></div> <script src="../jquery-1.9.1.min.js"></script> <script src="../code/popup.js"></script> </body> </html>
popup.js(生成表格HTML的脚本)
(function () { console.log("Entró"); init_code(); })(); /** * Function that initializes the page. */ function init_code() { try { // Initial variables: var html_code = ""; // Get all videos: browser.storage.sync.get(['all_videos']) .then((result) => { if (result.hasOwnProperty('all_videos') && result.all_videos) { if (result.all_videos && result.all_videos.length) { // Build initial HTML table code: html_code += `<table id="myTable"><tr><th>Thumbnail</th><th>Title</th><th>Channel</th><th>Channel_ID</th></tr>`; // Loop over the items and build the HTML with their data: result.all_videos.forEach((item) => { html_code += appendItem(item); }); // Finish the HTML table code: html_code += "</table>"; } else { // Show: "no items available": html_code = '<strong>No videos are stored on the localStorage.</strong>'; } } else { // Show: "no items available": html_code = '<strong>No videos are stored on the localStorage.</strong>'; } }, onErrorDetails); console.log("Ok!"); // Show the results: document.getElementById("allVideos").innerHTML = html_code; } catch (ex) { console.log("Error at the popup"); console.log("Error: " + ex.message); console.log("Stack: " + ex.stack); } } /** * Function that builds the HTML to be added on the main HTML div. * @param {object} item The item (i.e, the object that contains the video's data). * @returns string */ function appendItem(item) { return `<tr><img src='${item.Thumbnail}' alt='${item.Title}' /></tr><tr><span>${item.Title}</span></tr><tr><span>${item.Channel}</span></tr><tr><span>${item.Channel_ID}</span></tr>`; } /** * Function that handles the error(s) - if any - when the info is obtained from the localStorage. * @param {object} error_dt The object with the error details. */ function onErrorDetails(error_dt) { console.log("Error!"); console.log(error_dt); }
核心问题分析
- 脚本上下文冲突:manifest.json中同时将
popup.js放在background脚本和弹窗页面里,后台脚本的popup.js与弹窗的popup.js属于不同执行上下文,会导致逻辑混乱,且后台脚本不需要这个文件。 - 异步操作处理错误:
browser.storage.sync.get是异步Promise操作,当前代码在Promise完成前就执行了innerHTML赋值,此时html_code还是初始空字符串,无法更新DOM。 - 表格HTML结构错误:
appendItem函数返回多个独立的<tr>标签,每个数据单独占一行,不符合表格一行对应一条数据的结构,会导致渲染异常。 - 控制台查看方式错误:你可能查看的是YouTube页面的控制台,而非弹窗的控制台。弹窗的控制台需要右键点击弹窗空白处,选择“检查”才能打开。
- 数据存储验证缺失:未确认内容脚本(
Ejemplo.js、functions.js)是否正确将提取的视频数据存入browser.storage.sync的all_videos字段。
修复步骤
1. 修正manifest.json
移除background字段中的popup.js,因为它是弹窗专属脚本,不需要在后台运行:
// 删除这段代码 "background": { "scripts": [ "/code/popup.js" ] }
2. 修复popup.js的异步逻辑
将DOM更新代码移到Promise的then回调内,确保拿到数据后再渲染:
function init_code() { try { browser.storage.sync.get(['all_videos']) .then((result) => { let html_code = ""; if (result.hasOwnProperty('all_videos') && result.all_videos) { if (result.all_videos.length) { html_code += `<table id="myTable" class="s-table"><tr><th>Thumbnail</th><th>Title</th><th>Channel</th><th>Channel_ID</th></tr>`; result.all_videos.forEach((item) => { html_code += appendItem(item); }); html_code += "</table>"; } else { html_code = '<strong>No videos are stored.</strong>'; } } else { html_code = '<strong>No videos are stored.</strong>'; } // 拿到数据后再更新DOM document.getElementById("allVideos").innerHTML = html_code; }, onErrorDetails); } catch (ex) { console.log("Error at the popup"); console.log("Error: " + ex.message); console.log("Stack: " + ex.stack); document.getElementById("allVideos").innerHTML = '<strong>Failed to load data.</strong>'; } }
3. 修正表格行结构
修改appendItem函数,将一条视频的所有数据放在同一个<tr>的<td>中:
function appendItem(item) { return `<tr> <td><img src='${item.Thumbnail}' alt='${item.Title}' style="width:80px;" /></td> <td>${item.Title}</td> <td>${item.Channel}</td> <td>${item.Channel_ID}</td> </tr>`; }
4. 添加表格样式(可选)
在results.html的<head>中添加样式,匹配你需要的表格效果:
<style> .s-table { border-collapse: collapse; width: 100%; margin-top: 10px; } .s-table th, .s-table td { border: 1px solid #ddd; padding: 8px; text-align: left; } .s-table th { background-color: #f2f2f2; } </style>
5. 验证数据存储
检查内容脚本是否正确执行了数据存储,比如在Ejemplo.js中确保有类似代码:
// 假设提取到的视频数据存在videos数组中 browser.storage.sync.set({all_videos: videos}) .then(() => console.log("Videos stored successfully")) .catch(err => console.error("Storage error:", err));
6. 正确查看弹窗控制台
右键点击扩展弹窗的空白区域,选择“检查”,打开弹窗的开发者工具,查看console.log输出和错误信息。
关于弹窗HTML修改的确认
扩展的弹窗HTML完全可以通过JavaScript修改。弹窗是一个独立的HTML页面,拥有自己的DOM和执行上下文,和普通网页一样,你可以通过JavaScript任意操作DOM元素、修改内容或样式。
内容的提问来源于stack exchange,提问作者Mauricio Arias Olave
相关产品推荐
相关产品推荐

