Debounce Search Component di Vue.js

Dec 10 2022
Dari API Opsi ke API Komposisi
Pencarian adalah fungsi penting untuk sebagian besar aplikasi kehidupan nyata dan tantangan wawancara pengkodean yang sangat umum. Mari terapkan aplikasi sederhana yang mengambil data untuk API guna mendemonstrasikan beberapa konsep dasar Vue dan praktik terbaik.

Pencarian adalah fungsi penting untuk sebagian besar aplikasi kehidupan nyata dan tantangan wawancara pengkodean yang sangat umum. Mari terapkan aplikasi sederhana yang mengambil data untuk API guna mendemonstrasikan beberapa konsep dasar Vue dan praktik terbaik. Jika Anda hanya tertarik pada contoh API komposisi, lewati saja.

Antarmuka pengguna

Mari sederhanakan semuanya dengan membuat formulir hanya menggunakan masukan pencarian dan tombol untuk mengirimkannya.

<template>
  <form>
    <input type="search" placeholder="Search for products..." />
    <button>Search</button>
  </form>
</template>

Mari perkenalkan Vue. Kami membutuhkan cara untuk melacak nilai input, dan a v-modeladalah kasus penggunaan yang sempurna untuk itu. Selain itu, kita perlu melakukan pencarian saat tombol diklik. Kita dapat menggunakan click handler pada tombol itu sendiri, tetapi dengan menggunakan event submit pada form, kita memiliki dukungan keyboard secara gratis. Pencarian akan dilakukan dengan mengklik tombol dan pengiriman formulir dengan menekan tombol enter.

<template>
  <form @submit.prevent="performSearch">
    <input
      type="search"
      placeholder="Search for products..."
      v-model="searchTerm"
    />
    <button>Search</button>
  </form>
</template>

<script>
export default {
  name: "TheSearch",
  data() {
    return {
      searchTerm: "",
    };
  },
  methods: {
    performSearch() {
      // TODO
      // Perform search here
    },
  },
};
</script>

Untuk data, kami akan menggunakan layanan dummyJSON yang akan mengembalikan beberapa JSON tiruan dan API pengambilan asli . Untuk mengambil data, kita perlu membuat tautan dalam bentuk https://dummyjson.com/products/search?q=Laptop&limit=5Kami melakukannya di bantuan getSearchUrl menggunakan fungsionalitas URLSearchParams asli .

Kami menetapkan respons ke variabel reaktif yang disebut produk.

<script>
export default {
  name: "TheSearch",
  data() {
    return {
      searchTerm: "",
      products: [],
    };
  },
  methods: {
    async performSearch() {
      const searchUrl = this.getSearchUrl();
      const response = await (await fetch(searchUrl)).json();

      this.products = response.products;
    },
    getSearchUrl() {
      const url = "https://dummyjson.com/products/search";
      const params = {
        q: this.searchTerm,
        limit: 5,
      };

      const searchParams = new URLSearchParams(params);
      return `${url}?${searchParams}`;
    },
  },
};
</script>

Anda mungkin memperhatikan bahwa kami akan melakukan pencarian setiap kali formulir dikirimkan. Ini mungkin meluap server kami dan menyebabkan beberapa perilaku aneh jika beberapa respons dipenuhi dalam urutan yang berbeda dari yang dikirim. Untuk menghindari ini, kami dapat memperkenalkan debouncing.

Debouncing adalah teknik yang membungkus fungsi kita dengan fungsi proxy yang, selama terus dipanggil, tidak akan dipicu. Fungsi akan dipanggil setelah berhenti dipanggil untuk jumlah milidetik yang ditentukan.

Kita dapat mengimplementasikan fungsi debounce kita sendiri , tetapi kita akan menggunakan paket npm sebagai gantinya.

Sintaksnya terasa agak tidak wajar tetapi harus lebih jelas setelah melihat tanda tangan fungsi debounce debounce(fn, wait, [ immediate || false ])

<script>
import { debounce } from "debounce";

export default {
 ...
  methods: {
    performSearch: debounce(
      async function () {
        const searchUrl = this.getSearchUrl();
        const response = await (await fetch(searchUrl)).json();

        this.products = response.products;
      },
      600
    ),
   ...
  },
};
</script>

Cari Secara Otomatis

Memiliki tombol untuk mencari tidak umum saat ini. Mari lakukan pencarian secara otomatis menggunakan pengamat.

Selain itu, kami menambahkan beberapa validasi jika istilah penelusuran kosong atau terlalu pendek.

<script>
  ...
  watch: {
    searchTerm() {
      this.performSearch();
    },
  },
  methods: {
    performSearch: debounce(async function () {
      if (this.searchTerm === "") {
        this.products = [];
        return;
      }
      if (this.searchTerm.length < 2) {
        return;
      }
      const searchUrl = this.getSearchUrl();
      const response = await (await fetch(searchUrl)).json();

      this.products = response.products;
    }, 600),
   ...
</script>

Tidak ada yang menarik tentang komponen ini, tetapi kami tidak dapat memiliki fungsi pencarian tanpa hasil.

<template>
  <section>
    <h2>Products</h2>
    <div v-for="product in products" :key="product.id">
      <img :src="product.thumbnail" alt="product.title" />
      <h5>
        {{ product.title }}
      </h5>
      <p>
        {{ product.description }}
      </p>
      <hr />
    </div>
  </section>
</template>

<script>
export default {
  name: "SearchResults",
  props: ["products"],
};
</script>

<template>
    ...
    <SearchResults v-if="products.length" :products="products" />
</template>

<script>
import SearchResults from "./SearchResults.vue";

export default {
  name: "TheSearch",
  components: {
    SearchResults,
  },
  ...
};
</script>

Anda dapat menemukan solusi akhir untuk komponen pencarian yang di-debounce menggunakan API opsi di kotak pasir berikut .

API Komposisi

Vue 3 telah hadir, dan penggunaan API komposisi akan segera menjadi norma. Mengubah solusi kami untuk menggunakannya akan menarik. Ayo lakukan itu.

Konversi komponen Hasil Pencarian sepele karena hanya komponen presentasi.

Semuanya tetap sama di template, dan kita harus menggunakan definePropshelper di dalam script setupuntuk membuat template mengetahui produk.

<template>
  <section>
    <h2>Products</h2>
    <div v-for="product in products" :key="product.id">
      <img :src="product.thumbnail" alt="product.title" />
      <h5>
        {{ product.title }}
      </h5>
      <p>
        {{ product.description }}
      </p>
      <hr />
    </div>
  </section>
</template>

<script setup>
defineProps(["products"]);
</script>

  • Tambahkan setupke tag skrip
  • Deklarasikan data menggunakan ref
  • Perbarui referensi ke data dengan menambahkan .value
  • Hapus thissemuanya dapat diakses secara langsung
  • Deklarasikan watcher menggunakan watchhelper

<template>
  // Remains the same
</template>

<script setup>
import { debounce } from "debounce";
import { ref, watch } from "vue";
import SearchResults from "./SearchResults.vue";

const searchTerm = ref("");
const products = ref([]);

const getSearchUrl = () => {
  const url = "https://dummyjson.com/products/search";
  const params = {
    q: searchTerm.value,
    limit: 5,
  };
  const searchParams = new URLSearchParams(params);
  return `${url}?${searchParams}`;
};

const performSearch = debounce(async () => {
  if (searchTerm.value === "") {
    products.value = [];
    return;
  }
  if (searchTerm.value.length < 2) {
    return;
  }
  const searchUrl = getSearchUrl();
  const response = await (await fetch(searchUrl)).json();

  products.value = response.products;
}, 600);

watch(searchTerm, () => {
  performSearch();
});
</script>

Anda dapat menemukan solusi akhir untuk komponen penelusuran yang di-debounce menggunakan API komposisi di kotak pasir berikut .

Kesimpulan

Jadi ini dia. Komponen pencarian sederhana menggunakan debounce dalam format API Opsi dan Komposisi. Format baru membutuhkan waktu untuk membiasakan diri, tetapi jelas lebih bersih, dan saya yakin ini akan segera menjadi cara kami menulis komponen.

Artikel ini terinspirasi dari Advert Of Vue 2022 Day #1 Challenge.