Как изменить значение внутри тега, используя метод класса на чистом JavaScript?
Подскажите пожалуйста, как изменить значение внутри тега на конкретной карточки товара. Имеется класс, на основе которого создаются отдельные объекты - экземпляры класса. Эти объекты и есть отдельные карточки товара на странице.
class ProductItem {
constructor(name, description, category, image, price, type) {
this.name = name;
this.description = description;
this.category = category;
this.image = image;
this.price = price;
this.type = type;
this.quantity = 1;
}
increaseQuantity() {;
this.quantity = this.quantity + 1;
console.log("increase: ", this.name);
}
decreaseQuantity() {
if (this.quantity > 1) {
this.quantity = this.quantity - 1;
}
}
events() {
ROOT_RIGHT_SIDE.addEventListener("click", e => {
if (e.target.getAttribute("data-atr") === "inBasket") {
// вызвать ререндер корзины
}
if (e.target.getAttribute("data-atr") === "increase") {
this.increaseQuantity();
// увеличение на 1
}
if (e.target.getAttribute("data-atr") === "decrease") {
// уменьшение на 1
}
});
}
getTemplate() {
const html = `
<div class="item-wrapper" data-name="${this.name}">
<div class="item-wrapper__img"><img src="data${this.image}" alt="${this.category}"></div>
<div class="item-wrapper__name">${this.name}</div>
<div class="item-wrapper__description" data-atr="${this.type}">${this.description}</div>
<div class="item-wrapper__price">Цена: ${this.price} руб.</div>
<div class="item-wrapper__count">
<span>Количество</span>
<div class="item-count__button">
<button class="btn-count" data-atr="decrease">
<i class='fas fa-minus' data-atr='decrease'></i>
</button>
<span class="item-count__field">${this.quantity}</span>
<button class="btn-count" data-atr="increase">
<i class='fas fa-plus' data-atr='increase'></i>
</button>
</div>
<div class="item-wrapper__inbasket">
<button class="btn-style basket-btn-add" data-name="${this.name}" data-atr="inBasket">
В корзину
</button>
</div>
</div>
</div>`;
return html;
}
}
Вызов рендера карточек происходит в другом классе, Арр. Так же в нём вешается обработчик событий.
class App {
constructor() {}
async getProductsItem(productType) {
ROOT_RIGHT_SIDE.innerHTML = "";
const products = await request.fetchData(productType); // массив с продуктами
const productsItem = products.map(product => {
const { name, description, category, image, price, type } = product;
const item = new ProductItem(
name,
description,
category,
image,
price,
type
);
return item;
});
let content = "";
productsItem.forEach(element => {
content += element.getTemplate();
element.events(); // вешаем eventListener
});
ROOT_RIGHT_SIDE.insertAdjacentHTML("afterbegin", content);
}
}
Не знаю как изменить значение в поле, которое находится внутри шаблона.
<span class="item-count__field">${this.quantity}</span>
То есть в карточке товара есть кнопка (+) на которой весит дата-атрибут increase, соответственно при клике по ней у меня вызывается метод this.increaseQuantity() который и должен изменить значение в поле. Конечно можно обратиться к нему через querySelector, но может есть какие-то другие варианты лучше\правильнее?
Так же еще не могу понять(если посмотреть в метод this.increaseQuantity() у меня там есть console.log), почему по клику на кнопку(+) в консоле у меня отображается количество console.log()'ов равное количеству карточек на странице. Я ожидал, что мне покажет в консоле значение только того объекта у которого я нажимал по кнопе (+) :) Я как-то не правильно повесил обработчик событий....

ROOT_RIGHT_SIDE - это корневой враппер. Он есть в верстке изначально.
Заранее спасибо за ответ!
Ответы (1 шт):
Ниже пример с комментариями.
3 класса - инпут, кнопка и App - корневой, рендерит 2 кнопки и инпут, содержит всю логику.
Все это жутко неудобно. Почитайте документацию react, в разы быстрей придет понимание компонентного подхода, как для react в частности, так и для js в целом.
// класс Input, render возвращает input
class Input {
constructor(props) {
this.props = props;
this.notify = this.notify.bind(this); //биндим функцию оповещения
}
//ф-я оповещения, достаточно примитивно, просто принимает новое значение и устанавливает в элемент.
notify(newValue) {
this.element.value = newValue
}
render() {
//строим элементы, назначаем пропы и т.п.
this.element = document.createElement('input')
this.element.value = this.props.value || 0;
this.element.disabled = true;
this.props.subscribe(this.notify)
//возвращаем элемент.
return this.element;
}
}
// класс Button, render возвращает button
class Button {
constructor(props) {
this.onClick = props.onClick; //в пропах принимаем ф-ю для click эвента
this.value = props.value;
}
render() {
this.element = document.createElement('input');
this.element.type = "button";
this.element.value = this.value;
this.element.addEventListener('click', this.onClick) // назначаем на клик, эвент из пропов.
return this.element; // возвращаем элемент.
}
}
//родитель
class App {
constructor() {
this.count = 0;
this.increase = this.increase.bind(this); //биндим функции.
this.decrease = this.decrease.bind(this); //биндим функции.
this.subscribe = this.subscribe.bind(this) //биндим функции.
}
//ф-я подпики, передается в инпут, принимает коллбек ф-ю.
subscribe(newSub) {
this.subscriber = newSub;
}
//ф-я оповещения подписчика
notify() {
this.subscriber(this.count);
}
//ф-я увеличения
increase() {
this.count += 1;
this.subscriber && this.notify(this.count)
}
//ф-я уменьшения
decrease() {
this.count = this.count - 1;
this.subscriber && this.notify(this.count)//
}
render() {
// Описываем чилдренов.
this.children = [
new Button({
value: 'minus', //отправляем кнопке имя
onClick: this.decrease // забинженая ф-я уменьшения count
}),
new Input({
value: this.count, //отправляем инпуту стартовое значение
subscribe: this.subscribe //отправляем инпуту ф-ю для подписки на изменение count
}),
new Button({
value: 'plus', //отправляем кнопке имя
onClick: this.increase //забинженая ф-я увелиячения count
})
]
//перебираем массив чилдренов, инициируим у них render(), применяем их к родителю
this.element = this.children.reduce((acc, child) => {
acc.appendChild(child.render())
return acc
}, document.createElement('div'))
return this.element // возвращаем элемент
}
}
document.querySelector('#root').appendChild(new App().render()) //создаем элемент App и делаем его чилдреном #root
<div id='root'></div>