Фильтрация массива в JavaScript и вывод в DOM — повторение

Пример кода ниже — он работает, но кажется неуклюжим.

clients предоставляется из БД в виде json_encoded массив объектов (в реальном приложении это несколько сотен элементов).

Задача: фильтровать список на основе пользовательского ввода, который может быть частично нечувствительной к регистру строкой code или же name.

Пользователь заранее знает, что id или же name is — это для того, чтобы быстро сократить список до возможных совпадений, чтобы избавить их от пролистывания сотен.

 
document.addEventListener("DOMContentLoaded", function (event) {
    const clients = [{ id: 1, name: "Bob Marley", code: "BM1" }, { id: 2, name: "Elton John", code:"EJ1" }, { id: 3, name: "Beach Boys", code: "BB1" }, { id: 4, name: "Boyzone", code: "BO1" }];
    const clientsList = document.getElementById("clientsList");
    const search = document.getElementById("search");

    // handle empty client array?

    if (clients.length === 0) {
        clientsList.innerHTML = '<li>No clients were found.</li>';
    } else {

        // populate the list initially
        const listArray = clients.map((element) =>
            '<li><a href="https://codereview.stackexchange.com/clients/view/" + element.id + '">' + element.name + '</a></li>'
        ).join("");

        clientsList.innerHTML = listArray;

        search.addEventListener("keyup", function (event) {
            clientsList.innerHTML = clients.filter((value) =>
                value.name.toLowerCase().includes(event.target.value.toLowerCase()) ||
                value.code.toLowerCase().includes(event.target.value.toLowerCase())
            ).map((element) =>
                '<li><a href="https://codereview.stackexchange.com/clients/view/" + element.id + '">' + element.name + '</a></li>').join("");
        });
    }
});
<input type="text" id="search" placeholder="Search...">
<ul id="clientsList"></ul>

<!-- Sample input / output
bo => bob marley, beach boys, boyzone
on => elton john, boyzone
bm1 => bob marley -->

Мне не нравится, что есть повторение в создании li element а также url — Я подумал о создании функции, а затем использовании ее в map?

const generateListElement = (client_id, name) => `<li><a href="/clients/view/${client_id}">${name}</a></li>`;


...map((element) => generateListElement(element.id, element.name) 

но это выглядит не намного лучше.

хороший, плохой, уродливый?

1 ответ
1

Удалите внешний if else

if (clients.length === 0) {
  clientsList.innerHTML = '<li>No clients were found.</li>';
  return;
}  

Разделить const clients

Сделайте функцию. На данный момент clients жестко запрограммирован, позже переписан для работы с объектом JSON. Вызов функции не изменится

 const clients = fetchWhateverThatDataIs();

 function fetchWhateverThatDataIs() {
    return [{ id: 1, name: "Bob Marley", code: "BM1" }, { id: 2, name: "Elton John", code:"EJ1" }, { id: 3, name: "Beach Boys", code: "BB1" }, { id: 4, name: "Boyzone", code: "BO1" }];
 }

Объекты организуют функциональность, а затем упрощают клиентский код

А Clients объект будет инкапсулировать filter а также HtmlList.

function Clients (theClients) {
  this.clients = theClients ? theClients : [];
  
  this.isEmpty = function() { return this.clients.length === 0; }

  this.HtmlList = function () {
     return this.clients.map((element) =>
        '<li><a href="/clients/view/'%20+%20element.id%20+%20'">' + element.name + '</a></li>'
    ).join("");
  } //HtmlList

  // intended as an event handler
  this.filter = function (event) {
    this.clients.filter((value) =>           
      value.name.toLowerCase().includes(event.target.value.toLowerCase()) ||
      value.code.toLowerCase().includes(event.target.value.toLowerCase())
    ).map((element) =>
       '<li><a href="/clients/view/'%20+%20element.id%20+%20'">' + element.name + '</a></li>').join("");
  } //filter

} //Clients

<li> здание повторяется. Пока я склонен следовать моему правилу «повторил один раз — думай о рефакторинге, повторил дважды (или больше) — рефакторинг». В любом случае сначала убедитесь, что этот первоначальный рефакторинг работает.


это работает, но кажется неуклюжим

Уже нет.

document.addEventListener("DOMContentLoaded", function (event) {
  const clients = new Clients(fetchWhateverThatDataIs());
  const clientsList = document.getElementById("clientsList");
  const search = document.getElementById("search");

  if (clients.isEmpty()) {
    clientsList.innerHTML = '<li>No clients were found.</li>';
    return;
  }

  clientsList.innerHTML = clients.HtmlList();

  search.addEventListener("keyup", clients.filter);

});

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *