Javascript Chrome 扩展程序中的 onClick 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13591983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 12:25:54  来源:igfitidea点击:

onClick within Chrome Extension not working

javascriptgoogle-chrome-extensiononclick

提问by teeZee

This seems to be the easiest thing to do, but it's just not working. In a normal browser the .html and .js files works perfectly, but in the Chrome extension the onClickfunction is not performing what it's supposed to do.

这似乎是最容易做的事情,但它就是行不通。在普通浏览器中,.html 和 .js 文件可以完美运行,但在 Chrome 扩展程序中,该onClick功能没有执行它应该做的事情。

.js file:

.js 文件:

function hellYeah(text) {
  document.getElementById("text-holder").innerHTML = text;
}

.html file:

.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>

So basically once the user clicks "hyhy", "ha" should change into "xxx". And again - it works perfectly in the browser but does not work in the extension. Do you know why? Just in case I'm attaching the manifest.json below as well.

所以基本上一旦用户点击“hyhy”,“ha”应该变成“xxx”。再次 - 它在浏览器中完美运行,但在扩展中不起作用。你知道为什么吗?以防万一我也在下面附上 manifest.json。

Thanks in advance!

提前致谢!

manifest.json:

清单.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/"
  ]
}

回答by David

Chrome Extensions don't allow you to have inline JavaScript (documentation). You are going to have to do something similar to this.

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

Assign an ID to the link (<a onClick=hellYeah("xxx")>becomes <a id="link">), and use addEventListenerto bind the event. Put the following in your popup.jsfile:

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

回答by Xan

Reason

原因

This does not work, because Chrome forbids any kind of inline codein extensions via Content Security Policy.

这不起作用,因为 Chrome禁止通过内容安全策略在扩展程序中使用任何类型的内联代码

Inline JavaScript will not be executed. This restriction bans both inline <script>blocks andinline event handlers (e.g. <button onclick="...">).

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

How to detect

如何检测

If this is indeed the problem, Chrome would produce the following error in the console:

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

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

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

To access a popup's JavaScript console (which is useful for debug in general), right-click your extension's button and select "Inspect popup" from the context menu.

要访问弹出窗口的 JavaScript 控制台(通常对调试很有用),请右键单击扩展程序的按钮并从上下文菜单中选择“检查弹出窗口”。

More information on debugging a popup is available here.

此处提供有关调试弹出窗口的更多信息。

How to fix

怎么修

One needs to remove all inline JavaScript. There is a guide in Chrome documentation.

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

Suppose the original looks like:

假设原来的样子:

<a onclick="handler()">Click this</a> <!-- Bad -->

One needs to remove the onclickattribute and give the element a unique id:

需要删除该onclick属性并为元素提供唯一的 id:

<a id="click-this">Click this</a> <!-- Fixed -->

And then attach the listener from a script (which must be in a .jsfile, suppose popup.js):

然后从脚本附加侦听器(.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() {
  /* ... */
}

Note the wrapping in a DOMContentLoadedevent. This ensures that the element exists at the time of execution. Now add the script tag, for instance in the <head>of the document:

注意DOMContentLoaded事件中的包装。这确保元素在执行时存在。现在添加脚本标签,例如在<head>文档中:

<script src="popup.js"></script>

Alternative if you're using jQuery:

如果您使用的是 jQuery,则另一种选择:

// jQuery
$(document).ready(function() {
  $("#click-this").click(handler);
});

Relaxing the policy

放宽政策

Q:The error mentions ways to allow inline code. I don't want to / can't change my code, how do I enable inline scripts?

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

A:Despite what the error says, you cannotenable inline script:

A:不管错误是什么,你都不能启用内联脚本

There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes 'unsafe-inline'will have no effect.

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

Update:Since Chrome 46, it's possible to whitelist specific inline code blocks:

更新:从 Chrome 46 开始,可以将特定的内联代码块列入白名单:

As of Chrome 46, inline scripts can be whitelisted by specifying the base64-encoded hash of the source code in the policy. This hash must be prefixed by the used hash algorithm (sha256, sha384 or sha512). See Hash usage for <script>elementsfor an example.

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

However, I do not readily see a reason to use this, and it will not enable inline attributes like onclick="code".

但是,我不太容易看到使用它的理由,它不会启用内联属性,例如onclick="code".

回答by sergio0983

I had the same problem, and didn′t want to rewrite the code, so I wrote a function to modify the code and create the inline declarated events:

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

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, "< custom_id='"+item_with_event.custom_id+"'  ");
    }

    $(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');
})

This should remove all inline events from the selected node, and recreate them with jquery instead.

这应该从所选节点中删除所有内联事件,并使用 jquery 重新创建它们。

回答by Elias EstatisticsEU

I decide to publish my example that I used in my case. I tried to replace content in div using a script. My problem was that Chrome did not recognized / did not run that script.

我决定发布我在案例中使用的示例。我尝试使用脚本替换 div 中的内容。我的问题是 Chrome 无法识别/未运行该脚本。

In more detail What I wanted to do: To click on a link, and that link to "read" an external html file, that it will be loaded in a div section.

更详细地我想做的是:点击一个链接,然后点击一个链接来“读取”一个外部 html 文件,它将被加载到一个 div 部分。

  • I found out that by placing the script before the DIV with ID that was called, the script did not work.
  • If the script was in another DIV, also it does not work
  • The script must be coded using document.addEventListener('DOMContentLoaded', function() as it was told

        <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>
    
  • 我发现通过将脚本放在 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>
    

回答by jai gupta

As already mentioned, Chrome Extensions don't allow to have inline JavaScript due to security reasons so you can try this workaround as well.

如前所述,出于安全原因,Chrome 扩展程序不允许使用内联 JavaScript,因此您也可以尝试此解决方法。

HTML file

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

弹出窗口.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);
    }
}

Or if you are having a Jquery file included then

或者,如果您包含一个 Jquery 文件,那么

window.onclick = function(event) {
    var target = event.target ;
    if(target.matches('.clickableBtn')) {
        alert($(target).text());
    }
}