检查元素是否存在于点击事件

Check if element exists on click event

如何检查一个元素是否存在于父元素中?我在我的项目中为产品数量实现了一个 increase/decrease 按钮。当用户单击这些按钮时,我可以增加和减少数量。我有一个 _parentElement,它呈现一个元素和数据以及错误消息(这只会在出现错误时呈现)。我已将点击事件附加到该 _parentElement(这在 DOM 中可见)并执行事件委托。

仅当在 _parentElement 中呈现错误消息以及当我单击 _parentElement 时才会记录此错误。

错误Cannot read properties of null (reading 'innerHTML') at DetailView._handlerQuantity

这是我所做的:

View.js

import icons from 'url:../../icons/icons.svg';

export default class View {
  _data;
  
  renderError(message = this._errorMessage) {
    const html = /*html*/ `
      <div class="flex flex-col items-center justify-center gap-4 min-h-[inherit]">
        <svg class="h-6 w-6 sm:h-10 sm:w-10 fill-red-600">
          <use xlink:href="${icons}#icon-warning"></use>
        </svg>
        <span class="text-xl text-neutral-600 font-medium sm:text-xl xs:text-lg">${message}</span>
      </div>
    `;

    const markup = this._parseStringtoHTML(html);
    this._parentElement.innerHTML = '';
    this._parentElement.insertAdjacentElement('afterbegin', markup.body.firstElementChild);
  }
}

详情View.js

class DetailView extends View {
  _parentElement = document.querySelector(".product__details");
  _errorMessage = "We could'nt find the product. Please try another one!";

  constructor() {
    super();
    this._addHandlerProductQuanity();
  }

  _handlerQuantity(e) {
    const increase = e.target.closest(".btn__control--add");
    const decrease = e.target.closest(".btn__control--minus");
    let quantity = document.querySelector(".product__quantity");
    const currentValue = Number(quantity.innerHTML) || 0;

    if (increase)
      Number(quantity.innerHTML) < this._data.stocks
        ? (quantity.innerHTML = currentValue + 1)
        : 1;

    if (decrease)
      Number(quantity.innerHTML > 1)
        ? (quantity.innerHTML = currentValue - 1)
        : 1;
  }

  _addHandlerProductQuanity() {
    this._parentElement.addEventListener(
      "click",
      this._handlerQuantity.bind(this)
    );
  }
}

HTML:

<main class="main min-h-[calc(100vh-5rem)] sm:min-h-[calc(100vh-8rem)]">
  <section class="product__details min-h-[inherit]">
    <!-- PRODUCTS DETAILS WILL GO HERE... -->
  </section>
</main>

而不是这个:

const currentValue = Number(quantity.innerHTML) || 0;

你可以这样做:

const currentValue = Number(quantity?.innerHTML ?? 0);

?. 基本上会在尝试获取右侧的 属性 之前检查左侧的对象是否存在(在本例中为 quantity)(innerHTML).如果它不存在,那么它将 returned undefined。然后 ?? 将启动,而 return 0 将代替。

这解决了获取当前值的问题。

但是,您正在尝试设置一个可能不存在的事物的值。这是个坏消息。有几种方法可以解决这个问题,但最好的方法可能就是检查它是否是错误的,如果是,请继续创建它:

if (!quantity) {
  // code to create quantity and apparent it to its parent here
  // don't forget to set its default value to 0.
  // and assign it to quantity
}

或者,更好的是:

const quantity = document.querySelector('.product__quantity') ?? createQuantity(); 
// createQuantity() being the function that creates and returns the element.

如果将该块放在 const currentValue 行之前,则无需执行处理 null 的操作,只需执行以下操作即可:

const currentValue = Number(quantity.innerHTML);

另外,我不确定你想要这个位做什么:

Number(quantity.innerHTML) < this._data.stocks
    ? (quantity.innerHTML = currentValue + 1)
    : 1;

但是它是如何写的,最后一个 1 只是被扔掉并且什么都不做,所以,假设您只想增加数量,如果它少于当前库存,您应该将它重写为是:

currentValue < this._data.stocks && (quantity.innerHTML = currentValue + 1);

(还有,只小于,不小于等于?)

旁注:您可能应该使用 .textContent.innerText 而不是 .innerHTML 来获取数量,因为您不想要任何 HTML挂在那里,只有文本值。更好的是,根本不解析文本,只将值存储为 属性 ,当它发生变化时写出来:

 // initialize
 quantity.value = 0;

 // increment
 quantity.value++;
 quantity.innerText = quantity.value;

要创建 quantity 元素,您可以这样做:

function createQuantity() {
  // Use whatever element it should be
  const quantity = document.createElement('span');

  quantity.classList.add('product__quantity');

  // You'll probably need to tweak this to get it in the right spot
  __parentElement.appendChild(quantity);

  return quantity;
}