onclick 或内联脚本在扩展中不起作用
Posted
技术标签:
【中文标题】onclick 或内联脚本在扩展中不起作用【英文标题】:onclick or inline script isn't working in extension 【发布时间】:2021-11-26 12:42:48 【问题描述】:这似乎是最容易做的事情,但它就是行不通。在普通浏览器中,.html 和 .js 文件可以完美运行,但在 Chrome/Firefox 扩展中,onClick
函数没有执行它应该执行的操作。
.js 文件:
function hellYeah(text)
document.getElementById("text-holder").innerHTML = text;
.html 文件:
<!doctype html>
<html>
<head>
<title>
Getting Started Extension's Popup
</title>
<script src="popup.js"></script>
</head>
<body>
<div id="text-holder">
ha
</div>
<br />
<a onClick=hellYeah("xxx")>
hyhy
</a>
</body>
</html>
所以基本上一旦用户点击“hyhy”,“ha”应该变成“xxx”。再一次 - 它在浏览器中完美运行,但在扩展程序中不起作用。你知道为什么吗?以防万一我也在下面附上 manifest.json。
manifest.json:
"name": "My First Extension",
"version": "1.0",
"manifest_version": 2,
"description": "The first extension that I made.",
"browser_action":
"default_icon": "icon.png",
"default_popup": "popup.html"
,
"permissions": [
"http://api.flickr.com/"
]
【问题讨论】:
【参考方案1】:Chrome 扩展程序不允许您使用内联 javascript (documentation)。 Firefox WebExtensions (documentation) 也是如此。
你将不得不做类似这样的事情:
为链接分配一个ID(<a onClick=hellYeah("xxx")>
变成<a id="link">
),并使用addEventListener
绑定事件。将以下内容放入您的 popup.js
文件中:
document.addEventListener('DOMContentLoaded', function()
var link = document.getElementById('link');
// onClick's logic below:
link.addEventListener('click', function()
hellYeah('xxx');
);
);
popup.js
应作为单独的脚本文件加载:
<script src="popup.js"></script>
【讨论】:
我得到了类似这样的信息:“拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src 'self' chrome-extension-resource:”。” Javascript 不能在您的 HTML 文件中用于扩展。您必须从外部源加载所有 javascript。类似<script src="javascript.js"></script>
@teeZee 为了将来参考,在代码周围加上反引号 (`) 以将其格式化为 cmets。 Like this.
我的弹出窗口中的标记是在运行时生成的(例如,具有不可预测值的 标记)。我已将 标记的 id 设置为等于 标记 innerhtml 的值,如下所示:xxxxxx abc123 但我需要将值传递给 javascript 以便在单击它们时进行处理......我该怎么做?最终,只是让 javascript 来提醒单击的 href 的值将是一个好的开始。
请注意,即使你不能内联onclick="handleClick()"
,你仍然可以使用el.onclick = handleClick
。【参考方案2】:
如前所述,出于安全原因,Chrome 扩展程序不允许使用内联 JavaScript,因此您也可以尝试此解决方法。
HTML 文件
<!doctype html>
<html>
<head>
<title>
Getting Started Extension's Popup
</title>
<script src="popup.js"></script>
</head>
<body>
<div id="text-holder">ha</div><br />
<a class="clickableBtn">
hyhy
</a>
</body>
</html>
<!doctype html>
popup.js
window.onclick = function(event)
var target = event.target ;
if(target.matches('.clickableBtn'))
var clickedEle = document.activeElement.id ;
var ele = document.getElementById(clickedEle);
alert(ele.text);
或者如果你有一个 Jquery 文件,那么
window.onclick = function(event)
var target = event.target ;
if(target.matches('.clickableBtn'))
alert($(target).text());
【讨论】:
【参考方案3】:我决定发布我在我的案例中使用的示例。我尝试使用脚本替换 div 中的内容。我的问题是 Chrome 无法识别/没有运行该脚本。
更详细我想做的事情:单击一个链接,然后该链接“读取”一个外部 html 文件,它将被加载到一个 div 部分中。
我发现通过将脚本放在带有 ID 的 DIV 之前 被调用,脚本不起作用。 如果脚本在另一个 DIV 中,它也不起作用脚本必须使用 document.addEventListener('DOMContentLoaded', function() 进行编码
<body>
<a id=id_page href ="#loving" onclick="load_services()"> loving </a>
<script>
// This script MUST BE under the "ID" that is calling
// Do not transfer it to a differ DIV than the caller "ID"
document.getElementById("id_page").addEventListener("click", function()
document.getElementById("mainbody").innerHTML = '<object data="Services.html" class="loving_css_edit"; ></object>'; );
</script>
</body>
<div id="mainbody" class="main_body">
"here is loaded the external html file when the loving link will
be clicked. "
</div>
【讨论】:
我不确定....是否 100% 正常工作。 txt/html 定义已被删除。【参考方案4】:原因
这不起作用,因为 Chrome forbids any kind of inline code 通过内容安全策略在扩展程序中。
内联 JavaScript 将不会被执行。此限制禁止内联
<script>
块和内联事件处理程序(例如<button onclick="...">
)。
如何检测
如果这确实是问题所在,Chrome 会在控制台中产生以下错误:
拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src 'self' chrome-extension-resource:”。启用内联执行需要“unsafe-inline”关键字、哈希(“sha256-...”)或随机数(“nonce-...”)。
要访问弹出窗口的 JavaScript 控制台(通常对调试很有用),请右键单击扩展程序的按钮并从上下文菜单中选择“检查弹出窗口”。
有关调试弹出窗口的更多信息,请访问here。
如何解决
需要删除所有内联 JavaScript。有a guide in Chrome documentation。
假设原来的样子:
<a onclick="handler()">Click this</a> <!-- Bad -->
需要删除onclick
属性并给元素一个唯一的id:
<a id="click-this">Click this</a> <!-- Fixed -->
然后从脚本附加监听器(必须在.js
文件中,假设popup.js
):
// Pure JS:
document.addEventListener('DOMContentLoaded', function()
document.getElementById("click-this").addEventListener("click", handler);
);
// The handler also must go in a .js file
function handler()
/* ... */
注意DOMContentLoaded
事件中的包装。这可确保元素在执行时存在。现在添加脚本标签,例如在文档的<head>
中:
<script src="popup.js"></script>
如果您使用的是 jQuery,则另一种选择:
// jQuery
$(document).ready(function()
$("#click-this").click(handler);
);
放宽政策
问:错误提到了允许内联代码的方法。我不想/不能更改我的代码,如何启用内联脚本?
答:不管错误说什么,你cannot enable inline script:
没有机制可以放宽对执行内联 JavaScript 的限制。特别是,设置包含
'unsafe-inline'
的脚本策略将不起作用。
更新:自 Chrome 46 起,可以将特定的内联代码块列入白名单:
从 Chrome 46 开始,可以通过在策略中指定源代码的 base64 编码哈希来将内联脚本列入白名单。此哈希必须以使用的哈希算法(sha256、sha384 或 sha512)作为前缀。示例见Hash usage for
<script>
elements。
但是,我看不出使用它的理由,而且它不会启用像 onclick="code"
这样的内联属性。
【讨论】:
如果我想用类名而不是 Id 来做同样的事情。我试过但没有运气' 关于如何匿名化此解决方案以便它可以用于生成 div 名称的 Angular 应用程序的任何想法?我无法创建事件侦听器,因为按钮的名称对于我的 ng 重复中的每个项目都必须是唯一的... :(【参考方案5】:我有同样的问题,不想重写代码,所以我写了一个函数来修改代码并创建内联声明的事件:
function compile(qSel)
var matches = [];
var match = null;
var c = 0;
var html = $(qSel).html();
var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;
while (match = pattern.exec(html))
var arr = [];
for (i in match)
if (!isNaN(i))
arr.push(match[i]);
matches.push(arr);
var items_with_events = [];
var compiledHtml = html;
for ( var i in matches )
var item_with_event =
custom_id : "my_app_identifier_"+i,
code : matches[i][5],
on : matches[i][3],
;
items_with_events.push(item_with_event);
compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
$(qSel).html(compiledHtml);
for ( var i in items_with_events )
$("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function()
eval(items_with_events[i].code);
);
$(document).ready(function()
compile('#content');
)
这应该从所选节点中删除所有内联事件,并使用 jquery 重新创建它们。
【讨论】:
此代码执行不正确,请以正确的方式指导我以上是关于onclick 或内联脚本在扩展中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的“onclick()”事件在 Angular 中不起作用?
为啥内联“背景图像”样式在 Chrome 10 和 Internet Explorer 8 中不起作用?