Chrome扩展中使用第三方库求助:JsBarcode注入失败及代码优化
累计花费10小时、连续4天开发Chrome扩展,目标是将重命名为barcoddjs.js的JsBarcode条码库注入到目标网站https://www.ivory.co.il/*中生成条码,方便用户打印时传输数据,但始终无法成功运行。以下是现有代码,求第三方库的正确使用方法及代码优化建议:
现有代码
script.js
// Create a button element const button = document.createElement('button'); button.textContent = 'copy'; button.addEventListener('click', () => { if(document.getElementsByClassName("product-barcode")){ const makats = document.getElementsByClassName("product-barcode"); var makatstring = []; for (let i = 0; i < makats.length; i++) { makatstring[i] = makats[i].innerText.split(':')[1]; } } makatstring = makatstring.join('\n'); alert(makatstring) navigator.clipboard.writeText(makatstring); }); //button.addEventListener("mouseover", function() { // button.style.backgroundColor = "#f79e55"; //}); //button.addEventListener("mouseout", function() { // button.style.backgroundColor = "#f58221"; //}); const myDiv = document.querySelector(".topText"); button.style.fontSize = "20px"; button.style.backgroundColor = "#f58221"; button.style.color = "white"; myDiv.appendChild(button); document.addEventListener("DOMContentLoaded", function(event) { const locetion = document.querySelector("#app > div:nth-child(1) > div.row > div.col-12.col-md-4 > div.pull-left.d-none.d-md-block"); var div = document.createElement('div'); div.innerHTML = '<input type="search" id="mySearch" placeholder="Search for something..">'; let btn = document.createElement("button"); btn.onclick = function () { alert("Button is clicked"); }; btn.innerHTML = "Save"; btn.setAttribute('id','123123') locetion.append(div); locetion.append(btn); }); document.addEventListener("DOMContentLoaded", function(event) { const locetionbarcod = document.querySelector("#site-wrappah > div > div.topText"); var divqrcode = document.createElement('div'); divqrcode.innerHTML = '<svg id="barcode"></svg>'; //locetionbarcod.append(divqrcode); jsBarcode("#barcode", "Hi world!"); document.body.appendChild(divqrcode) generatecode(); }); function generatecode(){ alert("func work"); }
manifest.json
{ "name": "tempname", "description": "tempname", "version": "1.0", "manifest_version": 3, "permissions": ["storage", "activeTab", "contextMenus"], "content_security_policy": "script-src 'self'", "background": { "service_worker": "barcoddjs.js" }, "action": { "default_popup": "popup.html" }, "content_scripts": [ { "matches": ["https://www.ivory.co.il/*"], "js": ["script.js", "barcoddjs.js"] } ], "web_accessible_resources":[ { "resources": ["barcoddjs.js"], "matches": [ "https://www.ivory.co.il/*" ] }] }
注:
barcoddjs.js为JsBarcode条码库仅重命名,无其他修改。
第三方库正确使用方法(针对Manifest V3)
调整Content Script加载顺序
Content Script中需先加载依赖库barcoddjs.js,再加载业务代码script.js,否则调用jsBarcode时库未初始化会报错。修改content_scripts的js数组顺序:"content_scripts": [ { "matches": ["https://www.ivory.co.il/*"], "js": ["barcoddjs.js", "script.js"] } ]移除Background中的库引用
barcoddjs.js是依赖DOM的库,而Service Worker无DOM环境,放在background中会直接报错,需删除该配置:// 移除以下内容 "background": { "service_worker": "barcoddjs.js" },简化Web Accessible Resources(可选)
若仅在Content Script中使用该库,无需配置web_accessible_resources,可直接移除;若后续需向页面上下文注入库,再保留该配置。
代码优化建议
1. 合并重复的DOMContentLoaded监听
多次绑定DOMContentLoaded会导致冗余执行,合并为一个监听函数:
document.addEventListener("DOMContentLoaded", function(event) { // 原第一个DOMContentLoaded逻辑 const locetion = document.querySelector("#app > div:nth-child(1) > div.row > div.col-12.col-md-4 > div.pull-left.d-none.d-md-block"); if (locetion) { const div = document.createElement('div'); div.innerHTML = '<input type="search" id="mySearch" placeholder="Search for something..">'; const btn = document.createElement("button"); btn.onclick = () => alert("Button is clicked"); btn.innerHTML = "Save"; btn.setAttribute('id','123123'); locetion.append(div, btn); } // 原第二个DOMContentLoaded逻辑 const divqrcode = document.createElement('div'); divqrcode.innerHTML = '<svg id="barcode"></svg>'; document.body.appendChild(divqrcode); // 确保元素已插入DOM后再调用JsBarcode jsBarcode("#barcode", "Hi world!"); generatecode(); });
2. 优化条码数据提取逻辑
将HTMLCollection转为数组,用map简化循环,同时添加错误处理避免split失败:
button.addEventListener('click', () => { const makats = document.getElementsByClassName("product-barcode"); if (makats.length === 0) { alert("未找到条码元素"); return; } const makatstring = Array.from(makats) .map(item => { const parts = item.innerText.split(':'); return parts.length > 1 ? parts[1].trim() : ''; }) .filter(Boolean) .join('\n'); alert(makatstring); navigator.clipboard.writeText(makatstring); });
3. 避免未检查DOM元素导致的报错
获取DOM元素后先判断是否存在,再执行操作:
const myDiv = document.querySelector(".topText"); if (myDiv) { button.style.fontSize = "20px"; button.style.backgroundColor = "#f58221"; button.style.color = "white"; myDiv.appendChild(button); } else { console.warn("未找到.topText元素"); }
4. 使用CSS类管理样式(替代行内样式)
在Content Script中插入样式标签,便于维护:
// 插入样式 const style = document.createElement('style'); style.textContent = ` .copy-btn { font-size: 20px; background-color: #f58221; color: white; border: none; padding: 8px 16px; cursor: pointer; } .copy-btn:hover { background-color: #f79e55; } `; document.head.appendChild(style); // 给按钮添加类 button.classList.add('copy-btn');
5. 替换不稳定的元素选择器
避免使用#app > div:nth-child(1)这类依赖DOM结构的选择器,优先使用稳定的类名或属性选择器,减少页面结构变化导致的功能失效。
内容的提问来源于stack exchange,提问作者RYM8

