首页 > 解决方案 > Javascript 事件/序列问题:为什么这个事件会触发?

问题描述

我的应用程序中的一个页面有一些简单的用户偏好——例如,“登录/注销”。

该页面显示复选框...然后更新它们以显示用户的实际偏好(选中/未选中)。

然后,我想添加一个侦听器以确保捕获对此首选项的任何更改。

在下面的代码中(在“就绪”部分,因此它在页面加载时运行)我首先更新 HTML 以显示正确的开/关,然后为同一元素创建一个侦听器以捕获任何后续更改。

我显然不理解事件/冒泡 - 当此页面加载第一段代码时更新复选框,然后监听器触发......但由于代码的顺序,监听器还不存在。

我已经尝试了很多方法来阻止复选框的初始设置触发事件 - 下面的代码中的 stopPropagation。没有任何效果 - 由于此事件侦听器,我对我的服务器进行了不必要的更新。

帮助/指导表示赞赏。

if (arrUserData.userPrefWordLog === 1){
    $('#logMode').prop('checked', true).change(function (e) {
      console.log('ON - stop prop...2');
      e.stopPropagation();
    });
  } else {
    console.log('OFF - stop prop...1');
    $('#logMode').prop('checked', false).change(function (e) {
      console.log('OFF - stop prop...2');
      e.stopPropagation();
    });
  }

  console.log('Now set listener for CHANGE to wordPrefs...');
  // $('body').on('change', '.wordPref1', function () {
  $('#logMode').change(function () {
    console.log('Fire change to logMode...');
    updatePrefs();
  });

标签: javascriptjquery

解决方案


这是我在评论中提到的一个例子。它是纯 JS,我假设您可以弄清楚如何在 jQuery 中应用以适应您的代码。父容器上有一个更改事件侦听器。控制台将通过显示布尔值来显示哪个元素已更改以及是否已选中或未选中。

如果在父容器上使用单个侦听器不符合您的目的,则此代码仍应说明您不需要在更新上次保存的用户首选项的代码中的单个元素上使用两个更改事件侦听器。

我希望这有帮助。

我添加了示例的第二个版本,它不需要matches方法或按类或 ID 为每个单独的复选框搜索 DOM。如果您可以以类似的方式构造包含用户偏好的 HTML 和数据对象,则可以遍历 DOM 并利用 HTML 数据属性进一步简化代码。

第一个例子

"use strict";

let userPref_1 = 1, 
    userPref_2 = 0,
    userPref_3 = 1;

// Restore last selected user settings.

document.querySelector('.set_1').checked = userPref_1 === 1 ? true : false;
document.querySelector('.set_2').checked = userPref_2 === 1 ? true : false;
document.querySelector('.set_3').checked = userPref_3 === 1 ? true : false;

// Add change event listener to parent container.
document.querySelector('.parSet').addEventListener( 'change', chg_evt, false );

function chg_evt(evt)
  {
    let e = evt.target;
    if ( e.matches( '.set_1' ) )
       { console.log( 'Element set_1 changed to : ' + e.checked ); }
    else if ( e.matches( '.set_2' ) )
       { console.log( 'Element set_2 changed to : ' + e.checked ); }
    else if ( e.matches( '.set_3' ) )
       { console.log( 'Element set_3 changed to : ' + e.checked ); };

    // Invoke update user preferences function here.

  } // close chg_evt
<div class="parSet">
<label><input class="set_1" type="checkbox" role="button" unchecked>Setting One</label>
<label><input class="set_2" type="checkbox" role="button" unchecked>Setting Two</label>
<label><input class="set_3" type="checkbox" role="button" unchecked>Setting Three</label>
</div>

第二个例子

let userPrefs = [ 1, 0, 1 ], 
    p = document.querySelector('.parSet'),
    C = p.children,
    c, f;

// Restore last selected user settings.
for ( c of C )
 { 
   f = c.firstElementChild;
   f.checked = userPrefs[ f.dataset.i ] === 1 ? true : false;
 };

// Add change event listener to parent container.
p.addEventListener( 'change', chg_evt, false );

function chg_evt(evt)
  {
    let e = evt.target;
    console.log( 'User preference ' + ( parseInt(e.dataset.i) + 1 ) + ' changed to : ' + e.checked );     

    // Invoke update user preferences function here updatePrefs( e.dataset.i, e.checked) if needed.

  } // close chg_evt
<div class="parSet">
<label><input data-i="0" type="checkbox" role="button" unchecked>Setting One</label>
<label><input data-i="1" type="checkbox" role="button" unchecked>Setting Two</label>
<label><input data-i="2" type="checkbox" role="button" unchecked>Setting Three</label>
</div>


推荐阅读