Chrome扩展中的onClick不起作用

这似乎是最简单的事情,但它不工作。 在一个普通的浏览器中,.html和.js文件可以很好地工作,但是在Chrome扩展中, 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/" ] } 

Chrome扩展程序不允许使用embedded式JavaScript( 文档 )。 你将不得不做类似的事情。

为链接分配一个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'); }); }); 

原因

这是行不通的,因为Chrome通过内容安全策略禁止任何types的扩展内联代码 。

内联JavaScript不会被执行。 此限制禁止内联<script>内联事件处理程序(例如<button onclick="..."> )。

如何检测

如果确实是这个问题,Chrome会在控制台中产生以下错误:

拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src”self'chrome-extension-resource:“。 内联执行需要“不安全内联”关键字,散列('sha256 -…')或一个随机数('nonce -…')。

要访问一个popup式JavaScript控制台(通常对debugging很有用),右键单击您的扩展button,然后从上下文菜单中select“Inspect popup”。

有关debuggingpopup窗口的更多信息,请点击这里 。

怎么修

一个需要删除所有内嵌的JavaScript。 Chrome文档中有一个指南 。

假设原来的样子是这样的:

 <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); }); 

放宽政策

问:错误提到了允许内联代码的方法。 我不想/不能更改我的代码,如何启用内联脚本?

答:尽pipe错误说了什么,但不能启用内联脚本 :

没有放松对内嵌JavaScript执行限制的机制。 特别是,设置包含'unsafe-inline'的脚本策略将不起作用。

更新:自Chrome 46以来,可以将特定的内嵌代码块列入白名单:

从Chrome 46开始,通过在策略中指定源代码的base64编码哈希,可以将内联脚本列入白名单。 这个散列必须以所使用的散列algorithm(sha256,sha384或sha512)作为前缀。 有关示例,请参阅<script>元素的散列使用情况 。

但是,我不明白使用它的原因,并且不会启用onclick="code"等内联属性。

我有同样的问题,并不想重写代码,所以我写了一个函数来修改代码并创build内联声明的事件:

 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重新创build它们。