Chrome扩展:如何处理ShopWare POS技师名称样式重置及事件监听?
问题背景
我正在为汽修POS系统ShopWare开发Chrome扩展,将工单页面转换为车间大屏调度看板,核心需求:
- 移除页面冗余元素
- 放大技师名称
- 新工单添加闪烁动画,直至技师确认
遇到的问题:
- 注入的CSS中,闪烁动画(
.in-transition)生效,但h4.section-title和i.muted的字体大小设置无效,只能通过JS代码修改样式 - 当工单分配给技师时,页面触发软重载(动态更新DOM而非刷新页面),已通过JS修改的样式会被重置;尝试绑定
change、DOMContentLoaded事件均无法捕获样式重置的触发时机
附当前核心代码:
样式修改JS代码(enlarge-text.js)
const addStyleProp = () => { const className = "section-title"; const styleObj = { "font-size": "40px" }; elms = document.getElementsByClassName(className); for (let elm in elms) { let curr = elms[elm]; if (typeof curr === "object") { try { Object.assign(curr.style, styleObj); } catch (error) { console.log( "Error attempting to change styling on the current node.", elm ); } } } }; addStyleProp();
扩展注入配置(background.js)
const scriptFiles = ["scripts/removeElements.js", "./scripts/enlarge-text.js"]; const cssFiles = ["./css/blink.css"]; chrome.runtime.onInstalled.addListener(() => { chrome.action.setBadgeText({ text: "", }); }); const swRegex = new RegExp(".shop-ware.com"); chrome.action.onClicked.addListener(async (tab) => { //Check to see if we're on shopware. If not, bail. if (!(tab.url.search(swRegex) > 0)) { return; } const state = await chrome.action.getBadgeText({ tabId: tab.id }); //Already on. Notihng to do here! if (state === "ON") { return; } //set action badge to state await chrome.action.setBadgeText({ tabId: tab.id, text: "ON", }); await chrome.scripting.executeScript({ files: scriptFiles, target: { tabId: tab.id }, }); /**Blink the in-transition class and enlarge text*/ await chrome.scripting.insertCSS({ files: cssFiles, target: { tabId: tab.id }, }); });
注入的CSS(blink.css)
.in-transition{ animation: blink-animation 1s steps(5, start) none infinite; } @keyframes blink-animation { to{ visibility: hidden; } } h4.section-title { font-size: 40px; } i.muted { font-size: 40px; }
解决方案
A. 让注入的CSS字体大小设置生效
问题根源是原页面CSS的选择器优先级高于我们注入的样式,解决方式:
- 提升选择器优先级:使用更具体的选择器,或添加
!important强制覆盖
修改blink.css中的字体样式规则:
/* 方式1:增加父元素选择器提升优先级,建议优先使用 */ body .work-order-section h4.section-title { font-size: 40px; } /* 方式2:使用!important(优先级最高,仅在方式1无效时使用) */ h4.section-title { font-size: 40px !important; } i.muted { font-size: 40px !important; }
可通过Chrome开发者工具查看原页面的样式选择器,复制其结构并追加规则,确保优先级更高;避免滥用
!important,防止后续样式维护困难。
- 确认CSS注入顺序:扩展中
insertCSS在executeScript之后执行,确保注入的CSS在页面原有样式之后加载,覆盖效果更稳定。
B. 捕获样式重置的触发事件(应对软重载)
软重载本质是页面通过JS动态更新DOM,无法通过常规事件捕获,需使用MutationObserver监听DOM变化:
修改enlarge-text.js,替换单次执行的逻辑为持续监听:
const addStyleProp = () => { const className = "section-title"; const styleObj = { "font-size": "40px" }; // 使用for...of遍历HTMLCollection,避免遍历非元素属性 for (const elm of document.getElementsByClassName(className)) { if (elm instanceof HTMLElement) { Object.assign(elm.style, styleObj); } } }; // 初始化应用样式 addStyleProp(); // 创建DOM变化观察者 const observer = new MutationObserver((mutations) => { mutations.forEach(mutation => { // 检测到有新节点添加时,重新应用样式 if (mutation.addedNodes.length > 0) { addStyleProp(); } }); }); // 监听整个body的子节点变化(包含所有层级) observer.observe(document.body, { childList: true, subtree: true });
优化建议:
- 若知道工单列表的具体容器(如类名为
.work-order-container),可将监听目标改为该容器,减少不必要的性能消耗:
const targetContainer = document.querySelector('.work-order-container'); if (targetContainer) { observer.observe(targetContainer, { childList: true, subtree: true }); }
内容的提问来源于stack exchange,提问作者BJ Rutledge
相关产品推荐
相关产品推荐

