如何将事件传递给 JavaScript class 中的方法?
How to pass event into method in a JavaScript class?
这只是一个示例,我想我已经完成了使用或不使用箭头函数的所有操作,但仍然一无所获。我需要添加到方法 event.altKey
,但我如何才能像往常一样将 event
传递给它而无需 class?
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;
});
解决你的问题
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;
});
- 第一个任务是制作代码运行。
- 第二个任务将详细解释实际发生的情况以及为什么根本不需要 运行 具有 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 classes,最好让构造函数只负责最必要的引导部分。因此我们有一个初始化步骤,将 DOM 查询直接传递给构造函数。
接下来,命名 class List
是一种误导,因为 OP 主要将其用作结构元素,该元素具有专门操作列表项的功能。让我们将其重命名为 ListItems
.
然后每个 HTMLLIElement
添加两个自己的事件处理程序。使用 OP 的示例代码,它是两个箭头函数,每个接受一个 event
参数 但不将它 传递给预期的 class方法。
代码可能已经修复了......
list.addEventListener('click', (event) => this.click_green(event));
list.addEventListener('onmousedown', (event) => this.no_select_text(event));
...但更直观的方法是直接将 class 方法分配为事件处理程序,例如 ...
listItem.addEventListener('click', this.clickGreen, false);
listItem.addEventListener('onmousedown', this.noSelectText, false);
由于这两种方法的 this
上下文,已经走到这一步,人们开始与 class
方法作斗争。
click_green(event) { ... this.classList.add('selected') ... }
中的 this
不是 HTMLLIElement
,但 this
始终是 OP 的 List
class 的唯一实例在加载时创建。
与固定代码示例一样,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>
这只是一个示例,我想我已经完成了使用或不使用箭头函数的所有操作,但仍然一无所获。我需要添加到方法 event.altKey
,但我如何才能像往常一样将 event
传递给它而无需 class?
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;
});
解决你的问题
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;
});
- 第一个任务是制作代码运行。
- 第二个任务将详细解释实际发生的情况以及为什么根本不需要 运行 具有 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 classes,最好让构造函数只负责最必要的引导部分。因此我们有一个初始化步骤,将 DOM 查询直接传递给构造函数。
接下来,命名 class List
是一种误导,因为 OP 主要将其用作结构元素,该元素具有专门操作列表项的功能。让我们将其重命名为 ListItems
.
然后每个 HTMLLIElement
添加两个自己的事件处理程序。使用 OP 的示例代码,它是两个箭头函数,每个接受一个 event
参数 但不将它 传递给预期的 class方法。
代码可能已经修复了......
list.addEventListener('click', (event) => this.click_green(event));
list.addEventListener('onmousedown', (event) => this.no_select_text(event));
...但更直观的方法是直接将 class 方法分配为事件处理程序,例如 ...
listItem.addEventListener('click', this.clickGreen, false);
listItem.addEventListener('onmousedown', this.noSelectText, false);
由于这两种方法的 this
上下文,已经走到这一步,人们开始与 class
方法作斗争。
click_green(event) { ... this.classList.add('selected') ... }
中的 this
不是 HTMLLIElement
,但 this
始终是 OP 的 List
class 的唯一实例在加载时创建。
与固定代码示例一样,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>