如何将动态的 JavaScript 添加到动态生成的 HTML 元素中?

huangapple go评论65阅读模式
英文:

how to add dynamic JavaScript to dynamically generated Html elements?

问题

以下是代码的翻译部分:

function getWidgets(){
    
    var listUrl = base_url + widgetsPath + url_auth;
    
    console.log("发送GET请求至:" + listUrl);
    
    function getSuccess(obj){
        var dataWidget = obj.data;

        for (let i=0; i<dataWidget.length; i++){

            var id = dataWidget[i].id;
            var description = dataWidget[i].description;
            var price = dataWidget[i].pence_price;
            var url = dataWidget[i].url;
            var index = i;
            
            console.log("索引: ", i);
            console.log(dataWidget[i].id);
            console.log(dataWidget[i].description);
            console.log(dataWidget[i].pence_price);
            console.log(dataWidget[i].url);
            console.log(" ");
            
            var template = `<div class="container" class="product" id="productId_${index}">
                <form action="" class="product">
                    <img src="${url}"></img>
                    <p class="product_Description">${description}</p>
                    <input type="hidden" class="productId" value="${id}">
                    <input type="hidden" class="price" value="0.${price}">
                    <label for="quantity">Quantity:</label>
                    <input type="number" class="quantity" value="1" min="1">
                    <button class="submit">Add to cart</button>
                </form>
            </div>
            <script>
                document.addEventListener("DOMContentLoaded", () => {
                    const product${index} = document.querySelector("#productId_${index}");
                    product${index}.addEventListener("submit", e => {
                        e.preventDefault();
                        var formId = "productId_${index}";
                        productList(formId);
                    });
                });
            </script>`;
            
            $("#widgetContainer").append(template);

        }
        console.log("成功");
        console.log(dataWidget);
        
    };
    
    $.ajax(listUrl, {type: "GET", data: {}, success: getSuccess });
};

getWidgets();
英文:

I have an HTML page that gathers data from a database and uses that data to produce dynamic HTML elements. The problem is that these elements have to create a button that submits data without refreshing the page and then call a function productList(formId);.

This is the current function:

function getWidgets(){
    
    var listUrl = base_url + widgetsPath + url_auth;
    
    console.log(&quot;Sending GET to &quot; + listUrl);
    
    function getSuccess(obj){
        var dataWidget = obj.data;

        for (let i=0; i&lt; dataWidget.length; i++){

            var id = dataWidget[i].id;
            var description = dataWidget[i].description;
            var price = dataWidget[i].pence_price;
            var url = dataWidget[i].url;
            var index = i;
            
            
            console.log(&quot;index: &quot;,i);
            console.log(dataWidget[i].id);
            console.log(dataWidget[i].description);
            console.log(dataWidget[i].pence_price);
            console.log(dataWidget[i].url);
            console.log(&quot; &quot;);

            var template =`&lt;!-- product --&gt;
            &lt;div class=&quot;container&quot; class=&quot;product&quot; id=&quot;productId_${index}&quot;&gt;
                &lt;form action=&quot;&quot; class=&quot;product&quot;&gt;
                    &lt;img src=&quot;${url}&quot;&gt;&lt;/img&gt;
                    &lt;p class=&quot;product_Description&quot;&gt;${description}&lt;/p&gt;
                    &lt;input type=&quot;hidden&quot; class=&quot;productId&quot; value=${id}&gt;
                    &lt;input type=&quot;hidden&quot; class=&quot;price&quot; value=&quot;0.${price}&quot;&gt;
                    &lt;label for=&quot;quantity&quot;&gt;Quantity:&lt;/label&gt;
                    &lt;input type=&quot;number&quot; class=&quot;quantity&quot; value=&quot;1&quot; min=&quot;1&quot;&gt;
                    &lt;button class=&quot;submit&quot;&gt;Add to cart&lt;/button&gt;
                &lt;/form&gt;
            &lt;/div&gt;
            &lt;script&gt;
                        document.addEventListener(&quot;DOMContentLoaded&quot;,() =&gt;{
                            const product${index} = document.querySelector(&quot;#productId_${index}&quot;)
                            product1.addEventListener(&quot;submit&quot;,e=&gt;{
                                e.preventDefault();
                                var formId = &quot;productId_${index}&quot;;
                                productList(formId);
                            });
                        });
            &lt;/script&gt;
            &lt;!-- END product --&gt;`

            $(&quot;#widgetContainer&quot;).append(template);

        }
        console.log(&quot;success&quot;);
        console.log(dataWidget);
        
    };
    
    $.ajax(listUrl, {type: &quot;GET&quot;, data: {},success: getSuccess });
};

getWidgets();

答案1

得分: 1

不需要为每个附加到页面的小部件动态添加&lt;script&gt;块。相反,您可以添加一个单独的submit事件处理程序,它将能够处理您动态添加的所有&lt;form&gt;元素的submit事件。代码将如下所示:

$(&#39;#widgetContainer&#39;).on(&#39;submit&#39;, &#39;form.product&#39;, function (e) {
  e.preventDefault();
  const formId = $(this).parent().attr(&#39;id&#39;);
  productList(formId);
});

上面的代码使用事件委托来处理任何带有类名“product”的&lt;form&gt;元素的submit事件。在处理程序中,我们获取了&lt;form&gt;元素父元素的id属性。

这里提供了一个示例用于参考。

英文:

You do not need to dynamically add a &lt;script&gt; block for each widget you append to your page. Instead, you can add a single submit event handler that will be able to handle the submit event for all of the &lt;form&gt; elements you add dynamically. The code would look like the following:

$(&#39;#widgetContainer&#39;).on(&#39;submit&#39;, &#39;form.product&#39;, function (e) {
e.preventDefault();
const formId = $(this).parent().attr(&#39;id&#39;);
productList(formId);
});

The above code is using Event Delegation to handle the submit event for any &lt;form&gt; element with a class of "product". In the handler, we get the id attribute of the &lt;form&gt; element's parent.

Here is a fiddle for reference.

答案2

得分: 0

在底层,jQuery的append()方法使用Element.innerHTML解析HTML字符串。

如在MDN关于innerHTML的“安全注意事项”部分中提到:
> ... HTML规定使用innerHTML插入的<script>标签不应该执行。

所以,不要通过追加<script>标签来执行代码,而是直接执行它:

var template = /*没有<script>标签的模板*/;

$("#widgetContainer").append(template);

// <script>标签的代码
document.addEventListener("DOMContentLoaded", () => {
  const product = document.querySelector("#productId_${index}")
  product.addEventListener("submit", e => {
    e.preventDefault();
    var formId = "productId_${index}";
    productList(formId);
  });
});

或者更好的做法是,如76484的回答所示,使用事件委托。这样,您就不必添加单独的事件监听器。

英文:

Under the hood, jQuery's append() parses the HTML-string by using Element.innerHTML.

As mentioned in MDN's section Security considerations for innerHTML:
> ... HTML specifies that a &lt;script&gt; tag inserted with innerHTML should not execute.

So instead of executing the code by appending a &lt;script&gt; tag, simply execute it:

var template = /*without script tag*/;

$(&quot;#widgetContainer&quot;).append(template);

// Script tag&#39;s code
document.addEventListener(&quot;DOMContentLoaded&quot;,() =&gt; {
  const product = document.querySelector(&quot;#productId_${index}&quot;)
  product.addEventListener(&quot;submit&quot;, e =&gt; {
    e.preventDefault();
    var formId = &quot;productId_${index}&quot;;
    productList(formId);
  });
});

Or better, use event delegation as 76484's answer shows. That way you wouldn't have to add individual listeners.

huangapple
  • 本文由 发表于 2023年5月28日 19:40:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76351299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定