วิธีเพิ่มผู้ฟังเหตุการณ์แต่ละคนโดยใช้ jquery .each ()?

Jan 08 2021

ฉันมีการตั้งค่าง่ายๆ: ปุ่มสองปุ่มที่มีค่าต่างกัน ฉันต้องการใช้ฟังก์ชัน. each () จาก jquery เพื่อเพิ่มตัวฟังเหตุการณ์การคลิกให้กับแต่ละปุ่มที่บันทึกค่าของแต่ละปุ่ม แต่เมื่อใช้. each () jquery จะเขียนทับตัวจัดการการคลิกสำหรับปุ่มก่อนหน้า สิ่งนี้ทำให้ฉันมีคำถามสองข้อ:

  1. ทำไมถึงเป็นเช่นนั้น?
  2. จะเพิ่มผู้ฟังเหตุการณ์แต่ละคนในคอลเลกชันของวัตถุ jquery ได้อย่างไร?

ดูรหัสด้านล่าง

  <html lang="en">
    
    <head>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
        <script>
            $(() => { $(`button[toggle]`).each((_, button) => {
                    let $toggle = $(button);
                    type = $toggle.attr("type"); value = $toggle.attr("value");
                    $toggle.on("click", () => {
                        console.log(type, value);
                    });
                });
            });
        </script>
    
    </head>
    
    <body>
        <div>
            <button toggle type="one" value="true">One</button>
            <button toggle type="two" value="false">Two</button>
        </div>
    </body>
    
    </html>

คำตอบ

1 RoryMcCrossan Jan 08 2021 at 20:14

ปัญหาในโค้ดของคุณเกิดจากคุณได้ประกาศตัวแปรและโดยปริยายดังนั้นจึงอยู่ในขอบเขต ดังนั้นการวนซ้ำแต่ละครั้งต่อไปนี้จะเขียนทับค่าเพื่อให้เห็นเฉพาะค่าสุดท้ายเท่านั้นหลังจากการวนซ้ำสิ้นสุดลงtypevaluewindow

ในการแก้ไขปัญหานี้ให้กำหนดตัวแปรภายในลูป:

$(() => { $(`button[toggle]`).each((_, button) => {
    let $toggle = $(button);
    let type = $toggle.attr("type"); let value = $toggle.attr("value");
    $toggle.on("click", () => {
      console.log(type, value);
    });
  });
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<div>
  <button toggle type="one" value="true">One</button>
  <button toggle type="two" value="false">Two</button>
</div>

อย่างไรก็ตามคุณไม่จำเป็นต้องeach()วนซ้ำเลย คุณสามารถแก้ไขปัญหาและปรับปรุงคุณภาพโค้ดได้โดยเชื่อมโยงตัวจัดการเหตุการณ์เดียวกันกับbuttonองค์ประกอบทั้งหมดและใช้targetคุณสมบัติของเหตุการณ์ที่ยกขึ้นเพื่อเข้าถึงแอตทริบิวต์

นอกจากนี้โปรดทราบว่าtoggleในกรณีนี้การเพิ่มแอตทริบิวต์ที่ไม่ได้มาตรฐานของคุณเองอาจทำให้เกิดปัญหาใน UI และ JS แนวทางที่ดีกว่าคือการใช้คลาสเพื่อจัดกลุ่มองค์ประกอบ

สุดท้ายoneและtwoไม่ใช่ค่าที่ถูกต้องสำหรับtypeแอตทริบิวต์ ใช้dataแอตทริบิวต์แทนเพื่อแนบข้อมูลเมตาของคุณเองกับองค์ประกอบ

จากทั้งหมดที่กล่าวมาให้ลองทำดังนี้:

jQuery($ => {
  $('.toggle').on('click', e => { let $toggle = $(e.target); let type = $toggle.data("type"); 
    let value = $toggle.prop("value");
    console.log(type, value);
  });
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<div>
  <button class="toggle" data-type="one" value="true">One</button>
  <button class="toggle" data-type="two" value="false">Two</button>
</div>

1 prasanth Jan 08 2021 at 20:10

ใช้$(this)ภายในคลิกโทรกลับ

$(() => {
  $(`button[toggle]`).each((_, button) => { $(button).on("click", function(){
       type   = $(this).attr("type"); value = $(this).attr("value");
      console.log(type, value);
    });
  });
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>

และยังไม่จำเป็นต้องพูดถึงในการโทรกลับแต่ละครั้ง คุณสามารถโทรแบบปกติได้ตามด้านล่างนี้

$(() => { $(`button[toggle]`).on("click", function(){
       type   = $(this).attr("type"); value = $(this).attr("value");
      console.log(type, value);
    });
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>

Kostas Jan 08 2021 at 20:11
  1. เนื่องจากผู้ฟังผูกกับค่าสุดท้ายของ $ toggle
  2. โดยการสร้างและเรียกใช้ฟังก์ชันใหม่ดังที่แสดงในตัวอย่างข้อมูล

อธิบายได้ดีกว่าในคำถามนี้

<html lang="en">
    
    <head>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
        <script>
            $(() => {
                $(`button[toggle]`).each((_, button) => { let $toggle = $(button); type = $toggle.attr("type");
                    value = $toggle.attr("value"); $toggle.on("click", ((type, value) => {
                      return () => {
                        console.log(type, value);
                      };
                    })(type, value));
                });
            });
        </script>
    
    </head>
    
    <body>
        <div>
            <button toggle type="one" value="true">One</button>
            <button toggle type="two" value="false">Two</button>
        </div>
    </body>
    
    </html>