Javascript事件/序列问题:为什么会触发此事件?

时间:2019-10-19 22:33:10

标签: javascript jquery

我的应用程序中的页面具有一些简单的用户首选项-例如,“登录/注销”。

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

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

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

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

我已经尝试了多种方法来阻止复选框的初始设置触发事件-下面的代码中的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();
  });

2 个答案:

答案 0 :(得分:1)

这是我在评论中引用的示例。它使用纯JS,我认为您可以弄清楚如何在jQuery中应用以适合您的代码。父容器上有一个更改事件侦听器。控制台将通过显示布尔值来显示更改了哪个元素以及是否选中了该元素。

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

我希望这会有所帮助。

我添加了示例的第二个版本,该版本不需要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>

答案 1 :(得分:0)

如果您给出的整个代码都在ready函数中,则不应发生这种情况。该程序应按顺序执行。下面的代码在下面的JSFiddle中设置,该代码将显示在注册事件之前没有其他事件在触发。

  $('#logMode').prop('checked', true);
  $('#logMode').prop('checked', false);


  console.log('Now set listener for CHANGE to wordPrefs...');

  $('#logMode').change(function () {
    console.log('Fire change to logMode...');
  });

https://jsfiddle.net/ashhaq12345/rbnztvx0/4/

相关问题