You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅调用一次绑定函数,为动态生成的<li>绑定点击事件

How to Avoid Calling setupItemOnClick for Every Dynamically Created <li>

Great question! The issue with your current approach is that you're attaching separate click handlers to every .saveAs and .copy element as you create each <li>. This leads to redundant function calls and unnecessary event listeners cluttering the DOM.

The cleanest solution here is to use event delegation—a technique where you attach a single event listener to a parent element (like your .itemsUl <ul>) instead of each individual child. This listener will catch clicks from all matching child elements (even dynamically added ones) as the event bubbles up the DOM tree.

Step-by-Step Fix

  1. Update your template (optional but recommended)
    Add a data-id attribute to your <li> element. This makes retrieving the item ID more straightforward and avoids potential conflicts with the element's id property:

    <script type="text/html" id="itemTemplate">
      <li id="{{id}}" data-id="{{id}}">
        <div class="name" title="{{name}}">{{name}}</div>
        <div class="saveAs"></div>
        <div class="copy"></div>
      </li>
    </script>
    
  2. Refactor your myView function
    Remove the per-item setupItemOnClick call and replace it with a one-time event delegation setup on the parent <ul>:

    function myView() {
      const self = {};
      self.itemTemplate = null;
      self.myArrayOfObjects = null;
      self.itemsUl = null;
      self.mainContainer = null;
    
      self.initItemsUl = () => {
        self.itemsUl = self.mainContainer.find('.itemsUl');
        // Set up event delegation ONCE when initializing the list
        self.setupItemEventDelegation();
        self.myArrayOfObjects.forEach(self.initItemLi);
      };
    
      self.initItemLi = (item) => {
        const viewObj = { id: item.Id, name: item.Name };
        const itemLi = $(Mustache.render(self.itemTemplate, viewObj));
        // Append directly to the <ul> to maintain proper structure
        self.itemsUl.append(itemLi[0]);
        // No more per-item setup call needed here!
      };
    
      self.setupItemEventDelegation = () => {
        // Single listener for all .saveAs clicks
        self.itemsUl.on('click', '.saveAs', (event) => {
          // Fetch the item ID from the parent <li>'s data attribute
          const itemId = $(event.target).closest('li').data('id');
          do_something(itemId);
        });
    
        // Single listener for all .copy clicks
        self.itemsUl.on('click', '.copy', (event) => {
          const itemId = $(event.target).closest('li').data('id');
          do_something(itemId);
        });
      };
    
      return {
        init: (myArrayOfObjects, mainContainer) => {
          self.mainContainer = mainContainer;
          self.myArrayOfObjects = myArrayOfObjects;
          self.itemTemplate = $('#itemTemplate').html();
          Mustache.parse(self.itemTemplate);
          self.initItemsUl();
        }
      };
    }
    

Key Benefits of This Approach

  • One-time setup: setupItemEventDelegation runs only once when initializing the list, not for every <li> you render.
  • Improved performance: Fewer event listeners mean lower memory usage, especially with large lists.
  • Auto-handles new items: Any <li> elements added after the initial render will automatically work with the existing click handlers—no extra code required.

内容的提问来源于stack exchange,提问作者Shahar Shokrani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:44:42