1

这个问题已被解决

注意:您可以阅读解决方案和我进行的评估,感谢问题解释后的答案。

我正在尝试创建一个小的 JavaScript 脚本来解决用户的一些需求(UserLand 脚本)。

操作非常简单,为了尽可能简单,我需要在 DOM 中添加一些元素,包括 CSS、文本、函数等。

这样脚本就知道要创建什么元素、应用什么 CSS、什么文本等。我​​创建了一个具有以下形式的对象:

    options: {
      /* Button */
      'button': {
        'tagName'   : 'button',
        'innerHTML' : 'X',
        'css'       : {
          'position'          : 'fixed',
          'z-index'           : '9999999',
          'bottom'            : '20px',
          'left'              : '20px',
          'background-color'  : 'black',
          'cursor'            : 'pointer',
          'color'             : 'white',
          'width'             : '60px',
          'height'            : '60px',
          'border'            : 'none',
          'border-radius'     : '50%',
          'font-weight'       : 'bold',
          'font-size'         : '1.5rem'
        },
        'onClick'   : 'objectName.method()'
      }
    }

我的脚本通过循环执行以下代码:

    createElement: (element) => {
      
      /* Create element */
      const createElement = document.createElement( element.tagName );
      /* Add innerHTML */
      createElement.innerHTML = element.innerHTML;
      /* Add CSS */
      objectName.addCSStoElement( createElement, element.css );
      /* Add onClick event*/
      createElement.addEventListener( 'click', element.onClick, false );
      /* Add to DOM */
      document.body.appendChild ( createElement );

    }

一切正常运行,除了指令:

createElement.addEventListener( 'click', element.onClick, false );

我想这是因为它是一个字符串,这就是 JS 将它附加到“onClick”事件的方式。

假设我没记错的话,我该如何添加函数的名称,以便在单击创建的元素时可以执行它?

我希望我已经很好地表达了自己,并且我糟糕的英语不会导致混乱。

感谢您的时间和帮助,向大家问好!

问候,亚历克斯

解决方案:

我意识到我在暴露我的问题时提供的信息并不完整,例如,我没有说明它是全局对象还是本地对象,非常抱歉。

它是一个本地对象,在这种情况下,它是可以信任的代码,因为它是我自己在每次进入网站时注入到浏览器中的代码,目的是在某些任务中支持我。

考虑到这一点,我们可以继续,如果无论如何这不是你的情况,请考虑同事在他们的答案中添加的信息,它们非常有趣和重要。

我必须进行的更改是: 首先,在“选项”中修改“onClick”的值,如下所示:

'onClick'   : '(function(){objectName.method();})'

最后,我通过以下方式修改了将事件添加到 HTML 元素的方式:

createElement.addEventListener( 'click',eval(element.onClick), false );

而且,通过这些简单的更改,我设法解决并理解了问题所在!

非常感谢所有回复并给予我帮助和时间的人,祝你一切顺利!

4

3 回答 3

0

由于您专门询问使用字符串为字符串创建 HTML 事件处理程序,并且您知道您可以信任字符串的内容(它没有恶意内容),您可以使用setAttribute

createElement.setAttribute("onclick", element.onClick);

现场示例:

const objectName = {
    method() {
        console.log("objectName.method() called");
    }
};

const btn = document.createElement("button");
btn.textContent = "Click Me";
const onClick = "objectName.method()";
btn.setAttribute("onclick", onClick);
document.body.appendChild(btn);

请注意,它objectName必须是全局变量,而不是执行此操作的代码的本地变量。


或者,你可以按照这个问题的答案显示的方式来做,我在下面写了,然后才意识到我应该寻找一个副本(现在每个评论都没有被欺骗):

由于您可以信任包含代码的字符串的来源,因此您可以使用new Function该代码作为其主体来创建函数:

createElement.addEventListener( 'click', new Function(element.onClick), false );

不要使用您无法信任的字符串执行此操作。

请注意,代码引用的任何变量都必须是全局变量。

现场示例:

const objectName = {
    method() {
        console.log("objectName.method() called");
    }
};

const btn = document.createElement("button");
btn.textContent = "Click Me";
const onClick = "objectName.method()";
btn.addEventListener("click", new Function(onClick), false);
document.body.appendChild(btn);

如果你需要引用局部变量,你可以使用eval(同样:如果你不能相信文本的来源,不要这样做!你在ingeval!):

createElement.addEventListener( 'click', eval("(function() { " + element.onClick + "})"), false );

现场示例:

{ // A block so the code isn't at global scope
    const objectName = {
        method() {
            console.log("objectName.method() called");
        }
    };

    const btn = document.createElement("button");
    btn.textContent = "Click Me";
    const onClick = "objectName.method()";
    btn.addEventListener("click", eval("(function() { " + onClick + "})"), false);
    document.body.appendChild(btn);
}

于 2021-09-11T14:36:10.153 回答
0

我已经复制了您的示例并进行了必要的修改,现在它可以按预期工作。单击按钮时正在调用函数。

<html>
    <head><title>Example for string as function call</title></head>
    <body>
        <script type="text/javascript">
            let options = {
            /* Button */
            'button': {
                'tagName'   : 'button',
                'innerHTML' : 'X',
                'css'       : {
                    'position'          : 'fixed',
                    'z-index'           : '9999999',
                    'bottom'            : '20px',
                    'left'              : '20px',
                    'background-color'  : 'black',
                    'cursor'            : 'pointer',
                    'color'             : 'white',
                    'width'             : '60px',
                    'height'            : '60px',
                    'border'            : 'none',
                    'border-radius'     : '50%',
                    'font-weight'       : 'bold',
                    'font-size'         : '1.5rem'
                },
                //check how onClick method is changed
                'onClick'   : '(function(){console.log("hello");objectName.method();})'
            }
            };
            
            function createElement(element) {
                /* Create element */
                const createElement = document.createElement( element.tagName );
                /* Add innerHTML */
                createElement.innerHTML = element.innerHTML;
                /* Add CSS */
                objectName.addCSStoElement( createElement, element.css );
                /* Add onClick event*/
                //check how I am passing eval(element.onClick) instead of just element.onClick
                createElement.addEventListener( 'click',eval(element.onClick), false );
                /* Add to DOM */
                document.body.appendChild ( createElement );
            }

            createElement(options['button']);
        </script>
    </body>
</html>

正如TJ Crowder指出的那样:请确保objectName 是全局变量

于 2021-09-11T14:47:19.117 回答
0

您可以通过添加onclick属性并将代码字符串传递给配置对象中提供的方法来为按钮添加单击处理程序。

下面的示例将event对象添加为调用参数,以便该方法可以查看event.targetevent.currentTarget了解有关单击的内容的更多信息。

使用按钮并省略所有其他配置详细信息的示例:

// dummy object for testing:
const object = {
   name: {
      method: function(event) {
         alert(`You clicked '${event.target.textContent}'`)
      }
   }
}

// Create a button and add an "onclick" attribute set to a code string.
// This example adds the click event object as an argument for the method call


const button = document.createElement("button");
button.textContent = "click me";
button.setAttribute("onclick", "object.name.method(event)");
document.body.appendChild(button);

这是通过让 HTML 解析器将代码字符串转换为一个函数对象来实现的,该对象以单击event对象作为其参数来调用,就像onclick在 HTML 源代码中放置一个属性一样。

切勿对不受信任的代码执行此操作,但我假设配置数据来自应用程序代码,而不是来自用户或未经验证的输入。

设置属性不适合将多个事件处理程序添加到单个元素,但在内部它会创建一个函数来执行作为属性值提供的代码(字符串)并addEventListener为您调用。

于 2021-09-11T14:53:03.150 回答