如何将事件传入JavaScript类中的方法?

问题描述 投票:1回答:2

这里只是一个例子,我想我已经做了所有使用或不使用箭头函数的事情,但仍然一无所获。我需要在方法中加入 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;
});
javascript class oop arrow-functions
2个回答
1
投票
  • 第一个任务是让代码运行。
  • 第二个任务是要提供详细的解释,说明实际发生的情况,以及为什么完全不需要一个用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') ... } 并非 HTMLLIElementthis 始终是上位者的唯一实例。List 类在加载时被创建。

在加载时创建的 evt 对象与固定代码示例一样,提供了一个 target 和a currentTarget 对象。在给定的HTML结构中,这两个对象都持有对被点击的列表项的引用,只要一个列表项不再仅仅包含文本节点,而且也是其他HTML元素的父元素,这些元素可能是事件触发的目标。evt.currentTarget 是唯一的真相来源,因为它增加了两个事件处理程序。

在确定了被点击的列表项后,我们不希望仅仅查询父列表的所有列表项,因为列表项可能是其他列表的容器等等。相反,我们希望得到所有列表项的兄弟姐妹。parentNode 要知道 parentNode.childNodes 会列出任何节点,包括文本节点,例如,来自于所提供的示例代码的新行。一个总是在保存方面与 parentNode.children 这是个 HTMLCollection 只是列出元素节点.将这样的集合转换为数组......是需要通过数组方法来处理它的项目。Array.from(listItem.parentNode.children); ...是通过数组方法处理其项的必要条件。

关于如何使上位机的代码按照它的意图运行,没有什么可说的了。

而随着希望对代码有了更深入的理解,我们甚至可能会摆脱 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
投票

解决您的问题

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;
});
© www.soinside.com 2019 - 2024. All rights reserved.