Установіть прапорці з найновішої події .change ()

У мене виникають проблеми з фундаментальним питанням, але я не можу навіть з'ясувати, які належні умови для дослідження, щоб допомогти собі.

По суті, у мене є .change() слухач, який слухає зміни у прапорцях у div (вони перемикають шари Карта листівки). Я хочу створити змінну, яка зберігає список перевірених прапорців. Я можу це зробити, однак, мабуть, він зберігає окремі випадки перевірки шарів для кожного з випадків, коли спалахує слухач .change() . Деякий код, який має відтворити проблему:

var lyrs;

$("div#myID input:checkbox").change(function() {
    lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
    console.log('in .change(): ', lyrs)
    legendFunction( lyrs );

});

function legendFunction( lyrs ) {
    map.on('click', function() {
        console.log('in legendFunction: ', lyrs);
    });
};

Коли я друкую змінну в консолі в функції .change callback, існує один об'єкт lyrs . Проте, коли я надрукую його з функції зворотного виклику .on ('click') у legendFunction , він друкує список (через відсутність кращого слова) шарів, які були перевіряти під час кожного прапорця, якщо його було позначено або відмічено. На зображенні нижче показано це:

enter image description here

Що відбувається? Як отримати змінну lyrs у функції .on ('click') , щоб відповідати лише шарам для останнього .change() подія?

0

5 Відповіді

on method of jQuery will add an Event Listener to Event Queue, that is to say, it will add five Event Listeners to Event Queue if you call on method for five times.So, it will call Event Callback for five times when click Event is triggered, you should cancel all Event Listeners before using on method to bind Event Listener.

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

var lyrs;

$("div#myID input:checkbox").change(function() {
    lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
    console.log('in .change(): ', lyrs)
    legendFunction( lyrs );

});

function legendFunction( lyrs ) {
    map.off('click')
    map.on('click', function() {
        console.log('in legendFunction: ', lyrs);
    });
};
</div> </div>
0
додано

Ваша legendFunction додає обробник подій до вашої карти (це не показано, але я припускаю, що map у legendFunction є об'єктом jQuery, який представляє ваш актуальна карта). Проблема в тому, що він додає новий обробник подій кожного разу, коли ця функція виконується. З документації jQuery :

Що стосується jQuery 1.4, той же обробник подій може бути пов'язаний з елементом кілька разів.

І всі ці дубльовані обробники будуть стріляти, коли ця подія спрацьовує. Кожного разу, коли ви клацаєте прапорець, ваш прапорець змінює обробник, який, у свою чергу, викликає legendFunction , що додає новий обробник кліків на карту.

Ітерація 1

Перший раз через lyrs налаштовується як jQuery об'єкт перевірених прапорців, які будуть вказані на консолі. Немає жодного обробника подій для кліків на map (якщо legendFunction() також не запущено в іншому місці, або якщо ви додаєте ще один обробник натискання в іншому місці), то legendFunction (а точніше, обробники подій, які додає legendFunction ) не генерує жодного виводу консолі цього разу. Ця ітерація додає перший обробник подій map .

Ітерація 2

Наступного разу, коли буде встановлено прапорець, ви знову отримаєте правильний код , який буде зареєстровано в консолі. Ви не описали його, але якщо ваші прапорці фактично є на вашою map , то цей самий клік буде збільшено з прапорця до map і запустіть обробник кліків map , доданий також в ітерації 1. Залежно від вашої структури HTML, lyrs буде вже оновлюватися новим набором прапорець, і виводити обробник кліків map ітерації 1 відображатиме це. Крім того, цей виклик викликає legendFunction() , а також другий, дублюючий обробник подій map .

Ітерація 3

Як описано вище, за винятком тепер 2 ідентичних map обробників кліків, які генерують вихід на консолі. Додано третє дублікат обробника подій map .

... і т.д.

Я не знаю, в чому полягає мета, але щоб уникнути цієї проблеми, просто створіть обробник подій map

map.on('click', function() {
    console.log('map was clicked, layers are', lyrs);
});
0
додано

Це пояснюється тим, що ви прив'язуєте слухача до події кліків map кожного разу, коли ви викликаєте legendFunction . Це відбувається тому, що кожен раз, коли ця функція викликається, ви передаєте масив lyrs як параметр (який відрізняється від змінної lyrs , визначеної у верхній частині сценарію), а потім Ви робите прив'язку, тому ви створюєте закриття, яке запам'ятовує значення цього масиву за той час і за кожний наступний час, коли ви викликаєте функцію.

Ваша програма в основному робить це:

Установіть прапорець із ідентифікатором landfireEVT

  • In the change callback you'll have lyrs = ['landfireEVT']
  • When you call the legendFunction you add a new binding to the map element and it will "remember" lyrs = [landfireEVT]
  • If you click on the map element, the event that was just bound will fire and in the console you'll see the value of lyrs = ['landfireEVT']

Тепер хтось перевіряє прапорець ідентифікатора agc

  • In the change callback you'll have lyrs = ['landfireEVT','agc']
  • When you call the legendFunction you add a new binding to the map element and it will "remember" lyrs = ['landfireEVT','agc']
    • If you click on the map element, the first callback that was previously bound to the click event will fire and you'll see in the console lyrs = ['landfireEVT'], and after that the second callback that was just bound to the click event will fire and you'll see the value of lyrs = ['landfireEVT','agc']

Я хотів би прив'язувати подію лише один раз і зберігати оновлений список прапорців у змінній ліри

var lyrs;
map.on('click', function() {
   //lyrs will always be the variable defined above anytime somebody clicks on the map element.
   console.log('in legendFunction: ', lyrs);
 });

$("div#myID input:checkbox").change(function() {
  lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
  //add here any other logic you need to notify somebody else that a checkbox changed.
});

You can read more about closures and scope here https://community.risingstack.com/explaining-javascript-closure-scope-chain-examples/

0
додано

Проблема полягає в тому, що виклик подія Листівки реєструється кожного разу встановлено прапорець через legendFunction . Отже, кожен раз, коли ви натискаєте на карті, Leaflet виконує зворотний виклик зі значенням для lyrs , який був використаний для реєстрації зворотного виклику.

Можливо, ви бажаєте зареєструвати лише один обробник подій click . Щось на зразок цього:

HTML:

<div id="layer1" class="layers">
  <input type="checkbox" id="layer1" />
  
</div>

<div id="layer1" class="layers">
  <input type="checkbox" id="layer2" />
  
</div>

<div id="mapid"></div>

JavaScript:

var mymap = L.map('mapid').setView([51.505, -0.09], 8);

mymap.on('click', function() {
  $(".layers input[type='checkbox']:checked").each(function() {
    console.info(this.id, 'is checked');
  });
});
0
додано

Ваша повторна повторна подія кліків кілька разів. Спробуйте просто вивести значення лірів замість прив'язки ще раз у легендіFunction.

var lyrs;

$("div#myID input:checkbox").change(function() {
lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
console.log('in .change(): ', lyrs)
legendFunction( lyrs );

});

function legendFunction( lyrs ) {
        console.log('in legendFunction: ', lyrs);
};
0
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram