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

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

how to add dynamic JavaScript to dynamically generated Html elements?

问题

以下是代码的翻译部分:

  1. function getWidgets(){
  2. var listUrl = base_url + widgetsPath + url_auth;
  3. console.log("发送GET请求至:" + listUrl);
  4. function getSuccess(obj){
  5. var dataWidget = obj.data;
  6. for (let i=0; i<dataWidget.length; i++){
  7. var id = dataWidget[i].id;
  8. var description = dataWidget[i].description;
  9. var price = dataWidget[i].pence_price;
  10. var url = dataWidget[i].url;
  11. var index = i;
  12. console.log("索引: ", i);
  13. console.log(dataWidget[i].id);
  14. console.log(dataWidget[i].description);
  15. console.log(dataWidget[i].pence_price);
  16. console.log(dataWidget[i].url);
  17. console.log(" ");
  18. var template = `<div class="container" class="product" id="productId_${index}">
  19. <form action="" class="product">
  20. <img src="${url}"></img>
  21. <p class="product_Description">${description}</p>
  22. <input type="hidden" class="productId" value="${id}">
  23. <input type="hidden" class="price" value="0.${price}">
  24. <label for="quantity">Quantity:</label>
  25. <input type="number" class="quantity" value="1" min="1">
  26. <button class="submit">Add to cart</button>
  27. </form>
  28. </div>
  29. <script>
  30. document.addEventListener("DOMContentLoaded", () => {
  31. const product${index} = document.querySelector("#productId_${index}");
  32. product${index}.addEventListener("submit", e => {
  33. e.preventDefault();
  34. var formId = "productId_${index}";
  35. productList(formId);
  36. });
  37. });
  38. </script>`;
  39. $("#widgetContainer").append(template);
  40. }
  41. console.log("成功");
  42. console.log(dataWidget);
  43. };
  44. $.ajax(listUrl, {type: "GET", data: {}, success: getSuccess });
  45. };
  46. 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:

  1. function getWidgets(){
  2. var listUrl = base_url + widgetsPath + url_auth;
  3. console.log(&quot;Sending GET to &quot; + listUrl);
  4. function getSuccess(obj){
  5. var dataWidget = obj.data;
  6. for (let i=0; i&lt; dataWidget.length; i++){
  7. var id = dataWidget[i].id;
  8. var description = dataWidget[i].description;
  9. var price = dataWidget[i].pence_price;
  10. var url = dataWidget[i].url;
  11. var index = i;
  12. console.log(&quot;index: &quot;,i);
  13. console.log(dataWidget[i].id);
  14. console.log(dataWidget[i].description);
  15. console.log(dataWidget[i].pence_price);
  16. console.log(dataWidget[i].url);
  17. console.log(&quot; &quot;);
  18. var template =`&lt;!-- product --&gt;
  19. &lt;div class=&quot;container&quot; class=&quot;product&quot; id=&quot;productId_${index}&quot;&gt;
  20. &lt;form action=&quot;&quot; class=&quot;product&quot;&gt;
  21. &lt;img src=&quot;${url}&quot;&gt;&lt;/img&gt;
  22. &lt;p class=&quot;product_Description&quot;&gt;${description}&lt;/p&gt;
  23. &lt;input type=&quot;hidden&quot; class=&quot;productId&quot; value=${id}&gt;
  24. &lt;input type=&quot;hidden&quot; class=&quot;price&quot; value=&quot;0.${price}&quot;&gt;
  25. &lt;label for=&quot;quantity&quot;&gt;Quantity:&lt;/label&gt;
  26. &lt;input type=&quot;number&quot; class=&quot;quantity&quot; value=&quot;1&quot; min=&quot;1&quot;&gt;
  27. &lt;button class=&quot;submit&quot;&gt;Add to cart&lt;/button&gt;
  28. &lt;/form&gt;
  29. &lt;/div&gt;
  30. &lt;script&gt;
  31. document.addEventListener(&quot;DOMContentLoaded&quot;,() =&gt;{
  32. const product${index} = document.querySelector(&quot;#productId_${index}&quot;)
  33. product1.addEventListener(&quot;submit&quot;,e=&gt;{
  34. e.preventDefault();
  35. var formId = &quot;productId_${index}&quot;;
  36. productList(formId);
  37. });
  38. });
  39. &lt;/script&gt;
  40. &lt;!-- END product --&gt;`
  41. $(&quot;#widgetContainer&quot;).append(template);
  42. }
  43. console.log(&quot;success&quot;);
  44. console.log(dataWidget);
  45. };
  46. $.ajax(listUrl, {type: &quot;GET&quot;, data: {},success: getSuccess });
  47. };
  48. getWidgets();

答案1

得分: 1

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

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

上面的代码使用事件委托来处理任何带有类名“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:

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

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>标签来执行代码,而是直接执行它:

  1. var template = /*没有<script>标签的模板*/;
  2. $("#widgetContainer").append(template);
  3. // <script>标签的代码
  4. document.addEventListener("DOMContentLoaded", () => {
  5. const product = document.querySelector("#productId_${index}")
  6. product.addEventListener("submit", e => {
  7. e.preventDefault();
  8. var formId = "productId_${index}";
  9. productList(formId);
  10. });
  11. });

或者更好的做法是,如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:

  1. var template = /*without script tag*/;
  2. $(&quot;#widgetContainer&quot;).append(template);
  3. // Script tag&#39;s code
  4. document.addEventListener(&quot;DOMContentLoaded&quot;,() =&gt; {
  5. const product = document.querySelector(&quot;#productId_${index}&quot;)
  6. product.addEventListener(&quot;submit&quot;, e =&gt; {
  7. e.preventDefault();
  8. var formId = &quot;productId_${index}&quot;;
  9. productList(formId);
  10. });
  11. });

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:

确定