Как я могу обновить класс без setInterval при сравнении оператора if-else для classList.contains? - PullRequest
0 голосов
/ 20 января 2020

Мне нужно решение для сравнения if-else classList.contains в JavaScript. когда я сравниваю без setInterval, classList не работает, но мне нужно решение без setInterval, потому что оно обновляет все, что мне нужно, только для работы classList.contains при onclick. пожалуйста, смотрите код ниже.

let ctx = document.querySelector('.control');
ctx.onclick = () => {
  box.classList.toggle('rds');
  document.onclick = null; // important idea
  box.classList.remove('ok')

}

setInterval(() => {
  if (box.classList.contains('rds')) {
    document.onclick = () => {
      box.classList.remove('rds');
      box.classList.add('ok')
    }
  } else {
    document.onclick = null; // important idea
  }
}, 1)
.box {
  width: 200px;
  height: 200px;
  background: red;
  transition: 1s;
}

.rds {
  border-radius: 50%;
}

.ok {
  border: 10px dotted blue;
}
<button class="control">Control here</button>

<div class="box" id="box"></div>

Ответы [ 2 ]

0 голосов
/ 21 января 2020

Проблемы

OP 1 (он же O RIGINAL P oster - он же @ NIKHIL CHANDRA ROY ) использование ( неправильное использование? ... злоупотребление? ) из setInterval() - это просто средство для переключения "состояния" ( ex. .ok и .rds) из .box Я предполагаю.

Относительно неправильных представлений OP относительно (или, возможно, неспособности должным образом объяснить) следующего утверждения:

document.onclick = null; // important idea

Насколько я понимаю, OP обеспокоен тем, что document обнаружит событие щелчка и вызывать обработчик событий, тем самым вызывая два вызова обработчика событий в быстрой последовательности. Один раз на document, а другой на .control - отсюда и неправильное понимание того, что setInterval() был полезен в этой конкретной ситуации.


Обработчики событий / обратные вызовы 2

OP обрабатывает обработчики событий как обычные анонимные функции (именно поэтому OP создает две отдельные функции для изменения двух отдельных «состояний» и борьбы с , когда происходит звонок и когда вызов не должен ).

  • Стандартная анонимная функция
    Анонимные функции определяются и вызываются при разборе. Когда браузер замечает скобки ( например. function()), он интерпретирует его как: "Запустите эту функцию СЕЙЧАС " ).

    const nodeRef = () => {... 
    /* or */  
    var nodeRef = function() {...
    
  • Обработчик событий
    Обработчики событий - это функции, которые ждут, пока не произойдет зарегистрированное событие, прежде чем запустить . Обратите внимание на сходство, которое они разделяют:

    //~~~~ Defined (aka Named)
    domNode.onclick = functionName; 
    /* or */ 
    domNode.addEventListener('click', functionName);
    
    function functionName(eventObject) {...
    
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
    //~~~ Anonymous
    domNode.onclick = function(eventObject) {... 
    /* or */ 
    domNode.addEventListener('click', function(eventObject) {...
    
    • Когда инициируется зарегистрированное событие, вызывается обработчик события, поэтому включаются только круглые скобки, когда определен обработчик события. Обратите внимание, что определенный обработчик событий не имеет круглых скобок (), потому что их определения отображаются в верхней части.

    • Также по умолчанию обработчики событий передают объект события . Всегда включайте его в качестве первого параметра при определении обработчика события. Путем явной передачи объекта события (как правило, e, event, evt ...) обработчик события может получить доступ к свойствам объекта события, таким как event.type, event.currentTarget и event.target.

    • event.currentTarget - это объект (обычно HTMLElement ), который зарегистрирован в событии (it "слушает" для определенного события c). Он также упоминается как this в определении связанного с ним обработчика событий.
    • event.target - это объект, с которого произошло зарегистрированное событие. Например, если была нажата пятая кнопка из ста идентичных кнопок, event.target будет точно ссылаться на эту конкретную кнопку.

Надеемся, что такое обработчик события и что он делает немного яснее. Кроме того, насколько необходим объект события. В следующем разделе описываются фазы событий, в которых подробно описывается невидимая цепочка событий, происходящих в дереве DOM .


фазы событий

<!DOCTYPE html><!--document------------------?-->
<html><!-----------document.documentElement--?-->
 ...
   <body><!--------document.body-------------?-->
     <form id="ui"><!--document.forms.ui-----➕--HTMLFormElement Interface
                    ---event.currentTarget---➕--Registered to click event
                    ---this------------------?-->
       <button class='ctx'><!--event.target--⏬-->
         CLICKED!
       </button>
       <fieldset class='box ok'><!--event.target.nextElementSibling--?-❙-?-->
       </fieldset>
     </form>
    </body>
 </html>

? Фаза захвата

  • напр. Пользователь нажимает button.ctx и становится event.target
    • event.target родитель - event.currentTarget (ie form)
    • Путь события: document, html, body, form.
    • Путь (и текущая фаза захвата) заканчивается, когда родитель источника события (он же event.target) был достигнут.
    • Эта фаза редко используется специально разработчиком и обычно не учитывается (за некоторыми исключениями, такими как ключевые события)

? Целевая фаза

  • ex. После завершения пути от document до родительского элемента (ie document.forms.ui) button целевая фаза начинается
    • После определения event.target элемент, расположенный сразу после него (ie event.target.nextElementSibling), изменит "состояние" (.box.ok ИЛИ .box.rd).
    • Обработчик событий останавливает распространение (ie останавливает продолжение фазы барботирования), когда целевая фаза завершена или .ctx не нажата. Это желаемое поведение достигается с помощью конечного оператора: event.stopPropagation().
    • Путь к событию имеет только одну ссылку на event.target.
    • Этот этап является наиболее важным, поскольку он выделяет нажатых кнопки, даже если их было тысяча.

Pha Фаза барботирования

  • напр. Обычно после целевая фаза завершена, путь обратный.
    • Поскольку там, где нет других целей, бессмысленно продолжать цепочку событий, поэтому event.stopPropagation() предотвращает дальнейшее продвижение события click вверх по дереву DOM.
    • Кстати, это также исключает элементы / объекты-предки, такие как document, из события щелчка.

Рассмотрим шаблон программирования под названием Делегирование событий .

  • Преимущества

    • Несколько целевые элементы 3 (он же event.target) - ex. a <button> пользователь нажал) могут быть указаны и исключены нецелевые элементы 4 ( ex. document или body, которые могут помешать и помешать правильному поведению, если щелчок в любом месте вызовет обработчик события) .

    • Зарегистрировать только один элемент для обработки один или несколько целевых элементов одновременно .

    • К целевым элементам относятся также те, которые динамически добавляются в будущем.

  • Требования

    • Anc Элемент estor, который объединяет все te . Это может быть объект верхнего уровня, например document или window, но лучше назначить или создать элемент, максимально приближенный к te . Чем ближе, тем менее вероятно будет ошибочное поведение (например, двойные вызовы обработчиков событий).

    • Зарегистрировать событие для указанного элемента предка. Существует три способа регистрации элемента в событии, используя обычный JavaScript.

      • Событие свойства события
        Мой личный фаворит, потому что он краткий

        document.forms.ui.onclick = ctrl;
        
      • EventListener
        В общем случае наиболее рекомендуемый способ - единственное существенное различие между ними заключается в том, что третий необязательный параметр будет использовать вместо этого фазу захвата фазы пузырьков по умолчанию, передавая true.

        document.forms.ui.addEventListener('click', ctrl, true);
        
      • Событие атрибута события
        Этот способ обработки события так же стар, как грязь и его использование не рекомендуется из-за множества ограничений. Я включил его только ради полноты, НЕ РЕАЛИЗУЙТЕ ЭТУ ТЕХНИКУ .

        <form id='ui' onclick="ctrl(e); return false">
          <button class='ctx' type='button'>THIS IS LAME!</button>
          <fieldset class='box ok'></fieldset>
        </form> 
        
    • При определении обработчика событий, установите sh следующее:

      • Убедитесь, что текущий event.target (помните, что фазы событий не простаивают) не event.currentTarget. Как только это установит sh, сузьте возможности далее, используя управляющие или троичные операторы.

          ...
          if (event.target !== this) {
            if (event.target.classList.contains('ctx')) {...
          ...
        
      • Используя узкий критерий и используя event.stopPropagation(), исключить все остальное просто.

            ...
            } else {
              event.stopPropagation();
            }
          }
          event.stopPropagation();
        }
        

Демо

const ui = document.forms.ui;

ui.onclick = ctrl;

function ctrl(event) {
  const clicked = event.target;

  if (clicked !== this) {
    if (clicked.classList.contains('ctx')) {
      const box = clicked.nextElementSibling;
      box.classList.toggle('ok');
      box.classList.toggle('rd');
    } else {
      event.stopPropagation();
    }
  }
  event.stopPropagation();
}
.ctx {
  font-size: 1.5rem;
  cursor: pointer;
}

.box {
  width: 200px;
  height: 200px;
  background: red;
  border: 0;
  transition: 1s;
}

.rd {
  border-radius: 50%;
}

.ok {
  border: 10px dotted blue;
}
<form id='ui'>
  <button class="ctx" type='button'>Control</button>
  <fieldset class="box ok"></fieldset>
</form>

Сноски

1 В сообществе SO (не Конечно, в отношении SE в целом) OP используется взаимозаменяемо между O riginal P oster (участник, задающий вопрос) или O riginal P ost (сам вопрос).

2 Иногда термины обработчик событий , прослушиватель событий и callback могут использоваться для ссылки на функцию, вызываемую после событие происходит. Для целей этого ответа это верно. Более подробное объяснение см. В этом сообщении .

3 Термин целевые элементы ( te ) я придумал для ссылки на элементы в DOM, которые имеют общего предка и могут быть потенциальным event.target, возможным благодаря хорошо продуманному HTML / CSS и JavaScript, настроенным для эффективного делегирования событий.

4 Нецелевые элементы ( nte ) - это ad-ho c термин для описания элементов, которые должны быть исключенным из реагирования на определенные события по разным причинам. Обычно nte являются элементами / объектами-предками event.currentTarget, такими как document, body, et c. Хотя бывают моменты, когда высокоуровневые узлы в дереве DOM хорошо работают как event.currentTarget, лучше всего сохранять event.currentTarget как можно ближе к te , насколько это возможно.


Ссылки

Следующие ссылки охватывают другие аспекты, которые я не охватил полностью, чтобы избежать перегрузки информацией (ретроспективно, я считаю, что я потерпел неудачу).

HTMLFormElement

const ui = document.forms.ui;

.nextElementSibling

clicked.nextElementSibling;
0 голосов
/ 20 января 2020

Я вас понял. Но вы также должны обеспечить поведение вашей анимации. Я сделал 2 варианта без setInterval, пожалуйста, проверьте. И если это нормально для вас, отметьте ответ как правильный.

jsfiddle 1: https://jsfiddle.net/shuts13/dvp4tea9/21/

jsfiddle 2: https://jsfiddle.net/shuts13/0emocq7j/1/

<button class="control" onclick="update()">Control here</button>

    <div class="box" id="box">

    </div>


    function update() {
  const box = document.getElementById('box');

              box.classList.add('rds');
              box.classList.add('ok');

  setTimeout(()=> {
            if(box.classList.contains('rds')){
                            console.log('ECIS')
                box.classList.remove('rds');
            } 
  }, 1000)
  }
...