代码之家  ›  专栏  ›  技术社区  ›  Kondaveti Charan

EventListener的匿名函数和传递到EventListener中的已定义函数的工作方式不同?

  •  2
  • Kondaveti Charan  · 技术社区  · 3 年前

    我有一个div(.game space),包含6个子框,其中一个子框是具有绿色背景的('.activeBox)类的activebox,

    所以当我点击活动框时,它会将其类(.active box)移动到下一个提供绿色背景的框,这样它就一直移动到最后一个框。此外,我有重新启动按钮,当我点击它时,游戏应该重新启动,就像活动的盒子类被标记到第一个盒子,然后从这里再次移动到下一个盒子,并一直移动到点击时结束盒子。

    'use strict'
    const allBox = document.querySelectorAll('.box');
    const activeBox = document.querySelector('.active-box')
    const restartButton = document.querySelector('.restart-button')
    let active_box_index = activeBox_index_function();
    
    slideBox(allBox[active_box_index]);
    
    
    
    /* ======> code1  Anonymous function */
    /* 
    function slideBox(pass_active_box) {
      pass_active_box.addEventListener('click', function() {
        allBox[active_box_index].classList.remove('active-box')
        allBox[active_box_index + 1].classList.add('active-box')
    
        active_box_index = activeBox_index_function()
        slideBox(allBox[active_box_index]);
      })
    } */
    
    
    /* ======> code 2 , funtion defined oustside nad passed into EventListener*/
    
    function sliderfunction() {
      allBox[active_box_index].classList.remove('active-box')
      allBox[active_box_index + 1].classList.add('active-box')
    
      active_box_index = activeBox_index_function()
      slideBox(allBox[active_box_index]);
    }
    
    function slideBox(pass_active_box) {
      pass_active_box.addEventListener('click', sliderfunction);
    }
    
    
    // active box index
    function activeBox_index_function() {
      let index;
      allBox.forEach((el, indx) => {
        if (el.matches('.active-box')) {
          index = indx
        };
      })
      return index;
    }
    
    // when restart button clicked
    restartButton.addEventListener('click', function () {
      allBox[active_box_index].classList.remove('active-box')
      allBox[0].classList.add('active-box')
    
      active_box_index = activeBox_index_function()
    })
    @import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,600;0,700;0,800;0,900;1,800&display=swap');
    @import url('https://fonts.cdnfonts.com/css/common-pixel');
    
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
    }
    
    html {
        font-size: 62.5%;
        font-family: 'Poppins', sans-serif;
        color: black;
    }
    
    .game--section {
        height: 100vh;
        background-color: #252525;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .game-space {
        width: 80rem;
        height: 10rem;
        padding: 1rem;
        border-radius: 9px;
        background-color: #f5f5f5;
        display: grid;
        grid-template-columns: repeat(6, 1fr);
        gap: 1rem;
    }
    
    .box {
        background-color: tomato;
    }
    
    .active-box {
        background-color: #099268;
        cursor: pointer;
    }
    
    .restart-button {
        font-size: 3rem;
        cursor: pointer;
    }
    <body>
    
        <section class="game--section">
            <div class="game-space">
                <div class="box box1 active-box"></div>
                <div class="box box2"></div>
                <div class="box box3"></div>
                <div class="box box4"></div>
                <div class="box box5"></div>
                <div class="box box6"></div>
            </div>
            <div class="restart-button">🔁</div>
        </section>
    
        <script src="script.js"></script>
    </body>

    这是转折点 我尝试将Anonymous函数和在外部定义的function传递给addEventListener时相同的代码块传递给addEventListener。我看到两者的工作方式不同\

    code1)匿名函数块正在向DOM元素添加增量EventListener,由于双事件触发器,它正在跳过这些框。 code2)它没有增加DOM元素上的EventListener,这完全正常,我甚至没有添加removeEventListener不是DOM元素。

    有一次,尝试关闭代码1和代码2的注释,反之亦然,在2到3个活动框类转移到下一个框后,点击重新启动并尝试点击它们,你会得到我怀疑的。。。

    1 回复  |  直到 3 年前
        1
  •  2
  •   ADasGH    3 年前

    看起来,当您试图再次向事件侦听器添加已定义的函数时,它不会被添加,而匿名函数是真正的匿名函数,当您尝试再次向事件监听器添加相同的代码时,引擎不会将其标识为与前一个函数相同,因此会添加多个事件侦听器。看见 MDN Web Docs 了解更多信息。

    上面写着:

    如果函数或对象已经在事件侦听器列表中 对于该目标,不会再次添加函数或对象。

    以及:

    如果某个特定的匿名函数在事件侦听器列表中 为某个目标注册,然后在代码的后面 addEventListener调用中提供了相同的匿名函数 第二个函数也将添加到的事件侦听器列表中 那个目标。

    事实上,即使使用 重复调用相同的不变源代码,即使是在循环中。

        2
  •  0
  •   tatactic    3 年前

    我的英语很差,但如果我理解你的问题。。。

    你的 sliderfunction()

    如果 allBox[active_box_index + 1] 存在

    所以你可以在 滑块功能() 或在 activeBox_index_function()

    在下面的代码段中进行检查 滑块功能() 因此您可以避开日志: allBox[(active_box_index + 1)] is undefined"

    在这种情况下,当您到达方框的末尾时,最后一个方框将保持活动状态,直到您单击“开始”按钮。

        'use strict'
        const allBox = document.querySelectorAll('.box');
        const activeBox = document.querySelector('.active-box')
        const restartButton = document.querySelector('.restart-button')
        let active_box_index = activeBox_index_function();
    
        slideBox(allBox[active_box_index]);
    
    
    
        /* ======> code1  Anonymous function */
        /*
        function slideBox(pass_active_box) {
          pass_active_box.addEventListener('click', function() {
            allBox[active_box_index].classList.remove('active-box')
            allBox[active_box_index + 1].classList.add('active-box')
    
            active_box_index = activeBox_index_function()
            slideBox(allBox[active_box_index]);
          })
        } */
    
    
        /* ======> code 2 , funtion defined oustside nad passed into EventListener*/
    
        function sliderfunction() {
            //
          allBox[active_box_index].classList.remove('active-box')
            if((allBox[active_box_index + 1]!=undefined)){
                allBox[active_box_index + 1].classList.add('active-box')
            }else{
                allBox[allBox.length-1].classList.add('active-box')
            }
          
                
          active_box_index = activeBox_index_function()
          slideBox(allBox[active_box_index]);
        }
    
        function slideBox(pass_active_box) {
          pass_active_box.addEventListener('click', sliderfunction);
        }
    
    
        // active box index
        function activeBox_index_function() {
          let index;
          allBox.forEach((el, indx) => {
            if (el.matches('.active-box')) {
              index = indx
            };
          })
          return index;
        }
    
        // when restart button clicked
        restartButton.addEventListener('click', function () {
          allBox[active_box_index].classList.remove('active-box')
          allBox[0].classList.add('active-box')
          active_box_index = activeBox_index_function()
        })
            * {
                padding: 0;
                margin: 0;
                box-sizing: border-box;
            }
    
            html {
                font-size: 62.5%;
                font-family: 'Poppins', sans-serif;
                color: black;
            }
    
            .game--section {
                height: 100vh;
                background-color: #252525;
                display: flex;
                justify-content: center;
                align-items: center;
            }
    
            .game-space {
                width: 80rem;
                height: 10rem;
                padding: 1rem;
                border-radius: 9px;
                background-color: #f5f5f5;
                display: grid;
                grid-template-columns: repeat(6, 1fr);
                gap: 1rem;
            }
    
            .box {
                background-color: tomato;
            }
    
            .active-box {
                background-color: #099268;
                cursor: pointer;
            }
    
            .restart-button {
                font-size: 3rem;
                cursor: pointer;
            }   
        <section class="game--section">
            <div class="game-space">
                <div class="box box1 active-box"></div>
                <div class="box box2"></div>
                <div class="box box3"></div>
                <div class="box box4"></div>
                <div class="box box5"></div>
                <div class="box box6"></div>
            </div>
            <div class="restart-button">🔁</div>
        </section>