javascript - 为什么我的 Chrome 扩展弹出窗口没有重新绘制?
问题描述
我正在为我们基于 Web 的产品的内部用户编写一个 Google Chrome 扩展程序,他们可以在其中管理他们的功能标志。这是一个简单的 UI,包括需要接受的通知、人们可以在其中输入新功能标志的文本区域,以及带有删除按钮和复选框的这些标志的列表。然后,每当您访问该产品时,该扩展程序都会自动将标志添加到查询参数中,从而启用它们。
这很好用!至少在大多数情况下.. 我还不能弄清楚为什么,但是有些情况下用户单击图标,弹出窗口打开,并且弹出窗口的 html 没有正确响应。单击切换不会取消选中复选框,单击删除按钮不会删除功能标志,并且在您开始输入后聚焦文本框不会显示光标或任何文本。但是,如果您进行更改并关闭并重新打开弹出窗口,则更改确实会保存。
任何帮助将非常感激。
下面是代码。不相关的部分已替换为SNIP
。
清单.json
{
"name": "SNIP",
"version": "1.0",
"description": "SNIP",
"browser_action": {
"default_title": "SNIP",
"default_icon": "SNIP.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"manifest_version": 2,
"permissions": [
"storage",
"webNavigation",
"tabs"
]
}
popup.html
<html>
<head>
<style>
SNIP
</style>
</head>
<body>
<h3>Important notice:</h3>
<ol>
SNIP (just some li's with text in here)
</ol>
<button id="accept-notice">Accept</button>
<div id="feature-flag-container" class="hidden">
<h3>Feature flags:</h3>
<div id="feature-flag-list"></div>
<input id="new-feature-flag" type="text" />
</div>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
popup.js
const acceptNoticeButton = document.getElementById("accept-notice");
const featureFlagContainer = document.getElementById("feature-flag-container");
const featureFlagList = document.getElementById("feature-flag-list");
const newFeatureFlagInput = document.getElementById("new-feature-flag");
let existingFlags = [];
chrome.runtime.sendMessage({ msg: "open_popup" });
chrome.runtime.onMessage.addListener(request => {
Object.keys(request.featureFlags).forEach(flag => {
addFeatureFlagNode(flag, !!request.featureFlags[flag]);
});
if (request.acceptedNotice) {
acceptNoticeButton.click();
}
});
acceptNoticeButton.onclick = () => {
chrome.runtime.sendMessage({ msg: "accept_notice" });
acceptNoticeButton.classList.add("hidden");
featureFlagContainer.classList.remove("hidden");
}
function removeFeatureFlag(e) {
const parent = e.target.parentNode;
const flag = e.target.parentNode.children[1].innerText;
existingFlags = existingFlags.filter(f => f !== flag);
parent.remove();
chrome.runtime.sendMessage({ msg: "remove_flag", flag });
}
function toggleFeatureFlag(e) {
const flag = e.target.parentNode.children[1].innerText;
const value = e.target.checked === true;
chrome.runtime.sendMessage({ msg: "toggle_flag", flag, value });
}
function addFeatureFlagNode(flag, checked) {
existingFlags.push(flag);
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = checked === false ? false : true;
checkbox.onchange = toggleFeatureFlag;
const text = document.createElement("p");
text.innerText = flag;
const del = document.createElement("button");
del.innerText = "Delete";
del.onclick = removeFeatureFlag;
const container = document.createElement("div");
container.appendChild(checkbox);
container.appendChild(text);
container.appendChild(del);
featureFlagList.appendChild(container);
}
newFeatureFlagInput.onkeydown = e => {
const flag = e.target.value;
if (e.key === "Enter" && flag && !existingFlags.includes(flag)) {
chrome.runtime.sendMessage({ msg: "add_flag", flag });
addFeatureFlagNode(flag);
e.target.value = "";
}
}
背景.js
const urls = [SNIP];
const environments = [SNIP];
const worksOn = [SNIP];
const options = [];
urls.forEach(url => {
environments.forEach(environment => {
worksOn.forEach(link => {
options.push(`https://${url}${environment}.SNIP.com/${link}/`);
});
});
});
const state = { acceptedNotice: false, featureFlags: {} };
chrome.storage.sync.get(["acceptedNotice", "featureFlags"], result => {
state.acceptedNotice = result.acceptedNotice;
state.featureFlags = result.featureFlags || {};
});
chrome.runtime.onMessage.addListener(({ msg, flag, value }) => {
if (msg === "open_popup") {
chrome.runtime.sendMessage(state);
return
}
if (msg === "accept_notice") {
state.acceptedNotice = true;
} else if (msg === "add_flag") {
state.featureFlags[flag] = true;
} else if (msg === "remove_flag") {
delete state.featureFlags[flag];
} else if (msg === "toggle_flag") {
state.featureFlags[flag] = value;
}
chrome.storage.sync.set(state);
});
chrome.webNavigation.onBeforeNavigate.addListener(event => {
if (options.find(option => event.url.indexOf(option) === 0)) {
const flags = Object.keys(state.featureFlags).filter(flag => state.featureFlags[flag] === true)
const url = event.url.split("?");
const queryParams = (url[1] || "").split("&").filter(param => !!param).map(param => {
const split = param.split("=");
return { key: split[0], value: split[1] };
});
const initialLength = queryParams.length;
flags.forEach(flag => {
if (!queryParams.find(param => param.key === flag)) {
queryParams.push({ key: flag });
}
});
if (queryParams.length !== initialLength) {
chrome.tabs.update(event.tabId, {
url: `${url[0]}?${queryParams.map(param =>
param.value ? `${param.key}=${param.value}` : param.key
).join("&")}`
});
}
}
});
解决方案
推荐阅读
- javascript - 在 Firestore 中更新后返回新更新的文档
- javascript - 如何等到 image.src 在 image.onload 事件函数中设置?
- amazon-s3 - 根据策略无效:策略条件失败:["eq"、"$x-amz-storage-class"、"STANDARD_IA"]
- c - 是否可以从内核空间使用 DRM 驱动程序?
- javascript - 卡住滑块脚本。如何正确设计滑块功能?
- python - Python中函数的这个特性正式称为什么?
- c# - 如何在 Visual Studio 中使用 LINQPad 脚本?
- python - 有人可以帮我将其格式化为电话号码的形式:000-000-0000
- python - 为什么我在 AlienInvasion.py 上收到 NameError
- javascript - whatsapp的简单发送表格