У меня есть компонент, который отображает несколько объектов, один из которых — массив диапазонов.
Вот часть моего кода:
class MyComponent ... {
private targetSpan = HTMLElement;
componentDidMount() {
//Here I get some data that fills an array that has 6 values
}
...
...
...
private setActive(value) {
let target = this.targetSpan;
if (target.classList.contains('active')) {
target.classList.remove('active');
//do more things
}
else {
target.classList.add('active');
//do even more things
}
}
private splitMyThings() {
const returnThings: any[] = [];
forEach(array, thing => {
returnThings.push(
<span class = "thing" onClick = {() => this.setActive(thing)} ref = {elem => this.targetSpan = elem}>
{thing}
</span>
);
});
}
render() {
...
return <div class = "container">
...
<div class = "myTargets">
{this.splitMyThings()}
</div>
...
</div>;
}
}
Когда я смотрю результат в браузере, все диапазоны отображаются так, как я хочу, единственное, что, похоже, работает неправильно, это функция setActive (или даже что-то еще?). Независимо от того, какой диапазон я нажимаю, каждый раз, когда только последний получает активный класс, я совершенно не могу понять, как это исправить.
Надеюсь, у кого-то есть быстрое и простое решение или идея, как этого добиться. заранее спасибо!
Вы устанавливаете this.targetSpan
для каждого элемента, переопределяя назначение на каждой итерации. Я не совсем понимаю, как вы ожидаете, что это сработает?
Вы пытаетесь изменить «вещь» с помощью функции setActive
.
Но, глядя на setActive(value)
, вы на самом деле никогда ничего не делаете с value
в этом контексте, а вместо этого извлекаете его из своего класса с помощью , а вместо этого извлекаете его из let target = this.targetSpan;
В этом контексте я использую «ценность» для некоторых других задач. Я даже попытался передать функции два параметра (это, значение), и в функции я говорю «let target = event.target», но она все равно не работает.
Вот пример того, как вам следует подходить к чему-то вроде этого:
import { Component, render } from 'preact';
const CSS_TEXT = `
.thing {
cursor: pointer;
}
.selected {
color: red;
};
`;
class MyComponent extends Component {
state = {
// index of the selected item -- if your list items can change, you'll want a better identifier, such as the text.
selectedIdx: -1,
array: []
}
componentDidMount() {
// Just creating an array as you mention in the post
this.setState({ array: Array.from({ length: 6 }).map((_, i) => i) });
}
render() {
return (
<div>
<style>{CSS_TEXT}</style>
<ul>
{this.state.array.map((thing, i) => (
<li
class = {this.state.selectedIdx == i ? 'selected' : ''}
onClick = {() => this.setState({ selectedIdx: i })}
>
{thing}
</li>
))}
</ul>
</div>
);
}
}
render(<MyComponent />, document.getElementById('app'));
Можно протестировать в Preact REPL
Ссылки не подходят, а DOM API не похожи на .classList
. Вам также не следует использовать цикл forEach
для перебора одного списка и заполнения другого — для этого и нужен .map
.
Немного изменил ваш пример для лучшей демонстрации (сделав массив списком вместо диапазонов, добавив CSS для выбранных элементов), но его должно быть легко перевести обратно.
Большое спасибо за этот пример. Мне потребовалось довольно много времени (еще новичку), но теперь это работает!! :)
Было бы проще использовать
event.target
в обработчикеonClick
вместо ссылки.