事件切换侦听器

Event toggle listener

我正在尝试使用 ui.activeFilter() 方法更改某些样式,但它显示:

Cannot read property toggle of undefined.

然后我将变量 filterLinks 设置为全局范围。我不明白为什么它不起作用。

"use strict";

// UI elements
const filterLinks = document.querySelectorAll('a');
const itemsLeft = document.querySelectorAll('span');

// Event listeners
filterLinks.forEach(function(link) {
  link.addEventListener('click', check);
});

// Laptops
class Laptop {
    constructor(availability, price, brand) {
      this.availability = availability;
      this.price = price;
      this.brand = brand;
    }
}

// Filter methods
class UiMethod {
    activeFilter(dddd) {
        dddd.classList.toggle('checked');

        if(dddd.className === 'checked') {
            console.log("test");
        } else {
            console.log('Try again you can do it, you are close to the succes');
        }
    }
}

const ui = new UiMethod;

// Function helpers
function check(e) {

    ui.activeFilter(filterLinks);
    e.preventDefault();
}

Cannot read property toggle of undefined.

这里似乎引用了 toggledddd.classList.toggle。因此,dddd.classList 未定义。 classList 是在所有 DOM 元素对象上定义的 属性,因此 dddd 一定不是您认为的那样。

回顾dddd的定义,我们可以看到它被定义为filterLinks。看filterLinks,很明显是document.querySelectorAll('a')设置的。

检查 querySelectorAll 的文档告诉我们 returns:

A non-live NodeList containing one Element object for each element that matches at least one of the specified selectors or an empty NodeList in case of no matches.

因此,要访问查询找到的实际 DOM 元素对象,我们需要从 NodeList 中提取该对象。如果要对 找到的每个 元素执行 toggle 操作,最简单的方法是遍历 NodeList 和 运行 每个元素上的函数。一个NodeList是array-like,但它不是数组,所以我们需要将它转换成数组才能在上面使用forEach。这导致以下代码:

Array.from(dddd).forEach(element => element.classList.toggle('checked'));

这将取代这个:

dddd.classList.toggle('checked');

简单的解决方案,您的 check(e) 函数需要稍作更新。不用传递整个对象,只需要传递点击函数的e.target就可以只影响那个对象。

变化: ui.activeFilter(filterLinks);

至: ui.activeFilter(e.target);

"use strict";

// UI elements
const filterLinks = document.querySelectorAll('a');

// Event listeners
filterLinks.forEach(function(link) {
  link.addEventListener('click', check);
});

// Laptops
class Laptop {
    constructor(availability, price, brand) {
      this.availability = availability;
      this.price = price;
      this.brand = brand;
    }
}

// Filter methods
class UiMethod {
    activeFilter(dddd) {
        dddd.classList.toggle('checked');

        if(dddd.className === 'checked') {
            console.log("test");
        } else {
            console.log('Try again you can do it, you are close to the succes');
        }
    }
}

const ui = new UiMethod;

// Function helpers
function check(e) {
    ui.activeFilter(e.target);
    e.preventDefault();
}
.checked{
color:red;
}
<a href="#">test</a><BR>
<a href="#">test2</a><BR>
<a href="#">test3</a>