Как передать событие в метод в классе JavaScript? - PullRequest
1 голос
/ 01 мая 2020

Вот только пример, я думаю, что все сделал с использованием стрелок или без них, но все равно ничего не получил. Мне нужно было бы добавить к методу event.altKey, но как я могу передать event к этому, как мы обычно делаем, не имея класса?

HTML:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      .selected {
        background: #0f0;
      }
      li {
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    Кликни на элемент списка, чтобы выделить его.
    <br/>
    <ul id="ul">
      <li>Кристофер Робин</li>
      <li>Винни Пух</li>
      <li>Тигра</li>
      <li>Кенга</li>
      <li>Кролик. Просто Кролик.</li>
    </ul>
  <script src="script.js"></script>
  </body>
</html>

То, что я думаю, должно работать, но не:

window.addEventListener('load', function(){
  class List{
    constructor(){
      this.lists = document.querySelectorAll('li');

      this.lists.forEach((list) => {
        list.addEventListener('click', (event) => this.click_green);
        list.addEventListener('onmousedown', (event) => this.no_select_text);
      });
    }

    no_select_text(event){
      event.preventDefault;
      return false;
    }

    click_green(event){
      if (event.ctrlKey || event.metaKey)
      {
        this.classList.add('selected');
        return;
      }
      let allLists = this.parentNode.querySelectorAll('li');
      allLists.forEach(function(list){
        list.classList.remove('selected');
      });
      this.classList.add('selected');
    }
  }
  new List;
});

Ответы [ 2 ]

0 голосов
/ 01 мая 2020
  • Первая задача состояла в том, чтобы запустить код.
  • Вторая задача - дать подробное объяснение того, что на самом деле происходит и почему вообще не нужен подход, который работает с JavaScript class.

class ListItems{
  constructor(listItemQuery) {
    const listItems = this;

    listItemQuery.forEach((listItem) => {
      listItem.addEventListener('click', listItems.clickGreen, false);
      listItem.addEventListener('onmousedown', listItems.noSelectText, false);
    });
  }
  noSelectText(evt) {
    evt.preventDefault;
    return false;
  }

  clickGreen(evt) {
    const listItem = evt.currentTarget;

    if (evt.ctrlKey || evt.metaKey) {
      listItem.classList.add('selected');
      return;
    }
    const firstLevelListItems = Array.from(listItem.parentNode.children);

    firstLevelListItems.forEach(function(item) {
      item.classList.remove('selected');
    });
    listItem.classList.add('selected');
  }
}

function initializeListItems() {
  new ListItems(document.querySelectorAll('li'));
}
window.addEventListener('load', initializeListItems, false);
.as-console-wrapper { max-height: 100%!important; top: 0; }
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      .selected {
        background: #0f0;
      }
      li {
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    Кликни на элемент списка, чтобы выделить его.
    <br/>
    <ul id="ul">
      <li>Кристофер Робин</li>
      <li>Винни Пух</li>
      <li>Тигра</li>
      <li>Кенга</li>
      <li>Кролик. Просто Кролик.</li>
    </ul>
  </body>
</html>

Теперь исполняемый код был разбит на части для лучшей идентификации различных частей предоставленного примера OP.

Если один использует классы JS, всегда лучше, чтобы конструктор отвечал только за самую необходимую часть начальной загрузки. Таким образом, у нас есть шаг инициализации, который передает запрос DOM непосредственно конструктору.

Далее, присвоение имени классу List вводит в заблуждение, поскольку OP использует его главным образом в качестве структурирующего элемента, который содержит функциональные возможности, которые исключительно управляют элементы списка. Давайте теперь переименуем его в ListItems.

Каждый HTMLLIElement затем добавит к нему два собственных обработчика событий. В примере кода OP это дважды функция стрелки, каждый из которых принимает event аргумент , но не передает его методу предполагаемого класса.

Код может были исправлены так ...

list.addEventListener('click', (event) => this.click_green(event));
list.addEventListener('onmousedown', (event) => this.no_select_text(event));

... но более интуитивно понятным способом было назначение методов класса непосредственно как обработчики событий, например ...

listItem.addEventListener('click', this.clickGreen, false);
listItem.addEventListener('onmousedown', this.noSelectText, false);

После этого далеко не начинают бороться с подходом class из-за контекста this метода.

this в пределах click_green(event) { ... this.classList.add('selected') ... } не является HTMLLIElement, но this всегда является единственным случаем Класс OP List, созданный во время загрузки.

Объект evt, как в примере с фиксированным кодом, предоставляет объекты target и currentTarget. С заданной HTML -структурой оба содержат ссылку на элемент списка, на который, например, щелкнули. Как только элемент списка больше не просто содержит текстовые узлы, но и является родительским для других HTML элементов, которые могут быть целевыми объектами, инициирующими события, evt.currentTarget является единственным источником истины из-за обоих добавленных обработчиков событий.

Теперь, будучи уверенным в отношении элемента списка, по которому щелкнули, не нужно просто запрашивать все элементы списка родительского списка, поскольку элементы списка могут быть контейнерами для других списков и так далее. Вместо этого один хочет получить всех братьев и сестер элемента списка. Ориентируясь на них через parentNode, следует помнить, что parentNode.childNodes перечисляет любой узел, включая текстовые узлы, которые, например, происходят из новых строк предоставленного примера кода. Каждый всегда находится на стороне сохранения с parentNode.children, который является HTMLCollection, который просто перечисляет узлы элемента. Преобразование такой коллекции в массив ... Array.from(listItem.parentNode.children); ... необходимо для обработки ее элементов с помощью методов массива.

Больше нечего сказать о том, как заставить код OP работать так, как мог бы было задумано.

И, надеясь получить лучшее понимание кода, можно даже избавиться от синтаксиса class, заменив его другим подходом к структурированию кода ...

// list item module
//
// - written as immediately invoked function expression ...
// - ... mainly for encapsulation of domain specific code.
//
const ListItems = (function () {

  function preventSelection(evt) {
    evt.preventDefault;
    return false;
  }

  function selectItem(evt) {
    const listItem = evt.currentTarget;

    if (evt.ctrlKey || evt.metaKey) {

      listItem.classList.add('selected');

    } else {
      const firstLevelListItems = Array.from(listItem.parentNode.children);

      firstLevelListItems.forEach((item) => {
        item.classList.remove('selected');
      });
      listItem.classList.add('selected');
    }
  }

  function initializeListItems() {
    document.querySelectorAll('li').forEach((listItem) => {
      listItem.addEventListener('click', selectItem, false);
      listItem.addEventListener('onmousedown', preventSelection, false);
    })
  }

  // the module:
  return {
    initialize: initializeListItems
  };

}());

// another task ... 
window.addEventListener('load', ListItems.initialize, false);
.as-console-wrapper { max-height: 100%!important; top: 0; }
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      .selected {
        background: #0f0;
      }
      li {
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    Кликни на элемент списка, чтобы выделить его.
    <br/>
    <ul id="ul">
      <li>Кристофер Робин</li>
      <li>Винни Пух</li>
      <li>Тигра</li>
      <li>Кенга</li>
      <li>Кролик. Просто Кролик.</li>
    </ul>
  </body>
</html>
0 голосов
/ 01 мая 2020

Решение вашей проблемы

window.addEventListener('load', function () {
  class List {
    constructor() {
      this.lists = document.querySelectorAll('li');

      this.lists.forEach((list) => {
        list.addEventListener('click', (event) => {
          this.click_green(event)
        });
        list.addEventListener('onmousedown', (event) => {
          this.no_select_text
        });
      });
    }

    no_select_text(event) {
      event.preventDefault;
      return false;
    }

    click_green(event) {
      if (event.ctrlKey || event.metaKey) {
        event.target.classList.add('selected');
        return;
      }
      let allLists = event.target.parentNode.querySelectorAll('li');
      allLists.forEach(function (list) {
        list.classList.remove('selected');
      });
      event.target.classList.add('selected');
    }
  }
  new List;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...