Всякий раз, когда у нас есть список элементов, таких как продукты, очевидно, что на стороне клиента должна быть функция поиска элементов для лучшего взаимодействия с пользователем.

В Vue 3 Composition API мы можем легко создать панель поиска, используя вычисляемые свойства.

На самом деле, это один из идеальных случаев использования вычисляемых свойств.

Допустим, у меня есть компонент на основе страницы ProductList.vue, который будет отображать список продуктов, для которых я хочу добавить функцию поиска.

ProductList.vue

<template>
</template>
<script>
export default {
  setup() {},
};
</script>

Получить данные о продуктах из Firebase

Давайте сделаем HTTP-запрос на сервер, чтобы получить список продуктов.

Я использую Firebase в этом примере, однако вам не нужно знать Firebase, чтобы следовать за ним.

Более разумно получать данные, выполняя фактические HTTP-запросы, а не просто создавая массив списка элементов внутри компонента.

Если вы хотите узнать больше о том, как начать работу с Firebase в вашем проекте Vue, перейдите по этой ссылке здесь.

Я уже добавил несколько продуктов в Cloud Firestore, который является одной из баз данных, предлагаемых Firebase, и он выглядит так, как показано на рисунке ниже.

В нем есть коллекция под названием products, которая содержит список документов по продуктам.

Как видите, каждый документ продукта имеет несколько свойств:

  • Заголовок
  • УПК
  • Бренд и так далее.

Ничего фантастического!

Теперь… давайте загрузим данные в компонент.

Во-первых, импортируйте firebase вверху, а также импортируйте onMounted и reactive из vue.

Метод onMounted() — это один из методов жизненного цикла в Vue 3 Composition API, и он будет вызываться при добавлении компонента Vue в DOM.

Внутри функции setup() инициализируйте переменную products с помощью пустого массива, который позже будет содержать все продукты.

import firebase from "firebase";
import { onMounted, reactive } from "vue";
export default {
  setup() {
    const products = reactive([]);
    onMounted(async () => {
      try {
        const productsSnap = await firebase
          .firestore()
          .collection("products")
          .get();
        productsSnap.forEach((doc) => {
          products.push(doc.data());
        });
      } catch (e) {
        console.log("Error Loading Products");
      }
    });
    return { products };
  },
};

Существует два способа определения реактивных переменных в Vue 3 Composition API. Я предпочитаю использовать reactive вместо ref, когда это возможно, но иногда ref неизбежен.

Рекомендуем
Обязательно знать Ref и Reactive Различия In Vue 3 Composition API

Затем сделайте запрос к коллекции продуктов Firebase и просмотрите документы, а затем поместите их в массив продуктов.

Наконец, функции setup() возвращают массив товаров, чтобы шаблон имел к нему доступ!

Довольно просто!

Обычно я использую многоразовый файл модуля для выполнения всех асинхронных операций CRUD, но в этом примере я поместил все в один компонент, чтобы сделать эту статью короче.

Вы можете узнать больше о том, как создавать повторно используемые модули, а также компоненты в Vue 3 Composition API.

Показать список продуктов

Прокрутите массив продуктов и покажите заголовок, а также другую информацию в шаблоне.

<template>
  <div class="ui cards" style="margin: 10px">
    <div
      class="card ui fluid"
      v-for="product in products"
      :key="product.id"
      style="margin: 0"
    >
      <div class="content">
        <img class="right floated mini ui image" :src="product.imageURL" />
        <div class="header">{{ product.title }}</div>
        <div class="meta">
          {{ product.upc }} | {{ product.weight }} Kg |
          {{ product.itemsperpack }} pack
        </div>
      </div>
    </div>
  </div>
</template>

И вывод будет выглядеть так:

Я использую фреймворк Semantic UI CSS, чтобы ускорить процесс проектирования пользовательского интерфейса — не стесняйтесь использовать свой собственный фреймворк CSS.

Добавить пользовательский интерфейс панели поиска

Как вы знаете, в Vue 3 мы можем создавать несколько родственных элементов внутри тегов шаблона.

Итак, просто добавьте поле ввода поиска прямо над HTML-кодом списка продуктов.

<template>
  <div class="ui icon input" style="width: 100%">
    <input type="text" placeholder="Search..." />
    <i class="search icon"></i>
  </div>
  <div
      class="card ui fluid"
      v-for="product in products"
      :key="product.id"
      style="margin: 0"
    >
     ... 
</template>

И вид будет таким:

Рекомендуем
Проверка формы Vue JS 3 Composition API — страницы регистрации и входа

Реализуйте функциональность поиска с помощью вычисляемого свойства

Вы можете прикрепить событие keyup к полю ввода и таким образом реализовать функцию поиска, но это будет утомительно.

Лучше использовать вычисляемые свойства.

Давайте посмотрим это в действии.

Определите переменную с именем searchQuery внутри функции setup().

const searchQuery = ref("");

Затем привяжите его к полю ввода поиска с помощью директивы v-model.

<input type="text" placeholder="Search..." v-model="searchQuery" />

Наконец, создайте вычисляемое свойство SearchedProducts, которое фильтрует все элементы из массива товаров, соответствующие тексту searchQuery, и возвращает только соответствующие элементы в searchedProducts. множество.

const searchedProducts = computed(() => {
      return products.value.filter((product) => {
        return (
          product.title
            .toLowerCase()
            .indexOf(searchQuery.value.toLowerCase()) != -1
        );
      });
});

Важно преобразовать название продукта и текст searchQuery в нижний регистр перед проверкой совпадения с помощью метода indexOf.

Наконец, функция setup() возвращает искомые продукты.

setup() {
  ...
  return { searchedProducts, searchQuery };
}

Теперь все, что мне нужно сделать, это избавиться от products из инструкции return и изменить products на searchedProducts в сигнатуре цикла v-for в шаблон.

<template>
  <div class="ui cards" style="margin: 10px">
    <div
      class="card ui fluid"
      v-for="product in searchedProducts"
      :key="product.id"
      style="margin: 0"
    >
      ...
    </div>
  </div>
</template>

И это будет работать так, как ожидалось.

Так что же происходит?

Когда компонент смонтирован, Firebase извлекает данные из Cloud Firestore и отправляет их в массив products.

В то же время вычисляемое свойство searchedProducts фильтрует данные, соответствующие searchQuery, который в первый раз будет пустой строкой.

Это означает, что все продукты будут добавлены в массив searchedProducts в первый раз.

Когда мы начнем вводить текст в строке поиска, вычисляемое свойство searchedProducts будет иметь отфильтрованные продукты, которые мы затем пройдем в шаблоне.

Таким образом, нам не нужно иметь два набора кода шаблона — один для начальной загрузки, а другой — для отфильтрованного результата.

Иногда вы можете столкнуться с ситуацией, когда вычисляемое свойство начинает фильтрацию до завершения выборки данных.

В этом случае все, что нам нужно сделать, это заменить метод жизненного цикла onMounted() на onBeforeMount().

Вывод

Теперь вы видите, как легко реализовать функцию поиска в списке элементов, используя вычисляемые свойства в Vue 3 Composition API.

Исходный код доступен здесь

Рекомендуем
Проверка формы Vue JS 3 Composition API — страницы регистрации и входа