微信公众号
扫描关注微信公众号
博客大厅

如何实现一个搜索功能的 Hook?

原创 来源:博客站 阅读 0 03月23日 08:23 听全文

实现一个搜索功能的 Hook 可以帮助你在多个组件中复用搜索逻辑。这个 Hook 可以处理输入框的输入、触发搜索请求、管理加载状态和错误状态等。以下是如何实现一个搜索功能的 Hook 的详细步骤和示例:

1. 创建搜索功能的 Hook

首先,创建一个自定义 Hook useSearch,用于处理搜索逻辑。

// useSearch.js
import { ref, watch } from 'vue';

export function useSearch(searchFunction, initialQuery = '') {
  const query = ref(initialQuery);
  const results = ref([]);
  const loading = ref(false);
  const error = ref(null);

  async function performSearch() {
    if (query.value.trim() === '') {
      results.value = [];
      return;
    }

    loading.value = true;
    error.value = null;

    try {
      results.value = await searchFunction(query.value);
    } catch (err) {
      error.value = err;
    } finally {
      loading.value = false;
    }
  }

  watch(query, performSearch, { immediate: true });

  return {
    query,
    results,
    loading,
    error,
    performSearch
  };
}

2. 在组件中使用搜索功能的 Hook

在组件中,你可以使用 useSearch Hook 来处理搜索逻辑。

<template>
  <div>
    <input v-model="query" placeholder="Search..." />
    <p v-if="loading">Loading...</p>
    <p v-else-if="error">Error: {{ error.message }}</p>
    <ul v-else>
      <li v-for="result in results" :key="result.id">{{ result.name }}</li>
    </ul>
  </div>
</template>

<script>
import { useSearch } from './useSearch';

export default {
  setup() {
    const searchFunction = async (query) => {
      const response = await fetch(`https://api.example.com/search?q=${query}`);
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    };

    const { query, results, loading, error } = useSearch(searchFunction);

    return {
      query,
      results,
      loading,
      error
    };
  }
};
</script>

3. <script setup> 语法中使用搜索功能的 Hook

<script setup> 语法中,使用 useSearch Hook 更加简洁。

<template>
  <div>
    <input v-model="query" placeholder="Search..." />
    <p v-if="loading">Loading...</p>
    <p v-else-if="error">Error: {{ error.message }}</p>
    <ul v-else>
      <li v-for="result in results" :key="result.id">{{ result.name }}</li>
    </ul>
  </div>
</template>

<script setup>
import { useSearch } from './useSearch';

const searchFunction = async (query) => {
  const response = await fetch(`https://api.example.com/search?q=${query}`);
  if (!response.ok) {
    throw new Error('Network response was not ok');
  }
  return response.json();
};

const { query, results, loading, error } = useSearch(searchFunction);
</script>

4. 处理防抖

为了防止频繁触发搜索请求,可以在 useSearch Hook 中添加防抖功能。

// useSearch.js
import { ref, watch } from 'vue';

export function useSearch(searchFunction, initialQuery = '', debounceDelay = 300) {
  const query = ref(initialQuery);
  const results = ref([]);
  const loading = ref(false);
  const error = ref(null);

  let timeout;

  async function performSearch() {
    if (query.value.trim() === '') {
      results.value = [];
      return;
    }

    loading.value = true;
    error.value = null;

    try {
      results.value = await searchFunction(query.value);
    } catch (err) {
      error.value = err;
    } finally {
      loading.value = false;
    }
  }

  watch(query, (newQuery) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      performSearch();
    }, debounceDelay);
  }, { immediate: true });

  return {
    query,
    results,
    loading,
    error,
    performSearch
  };
}

5. 在组件中使用带防抖的搜索功能 Hook

在组件中,你可以使用带防抖的 useSearch Hook。

<template>
  <div>
    <input v-model="query" placeholder="Search..." />
    <p v-if="loading">Loading...</p>
    <p v-else-if="error">Error: {{ error.message }}</p>
    <ul v-else>
      <li v-for="result in results" :key="result.id">{{ result.name }}</li>
    </ul>
  </div>
</template>

<script>
import { useSearch } from './useSearch';

export default {
  setup() {
    const searchFunction = async (query) => {
      const response = await fetch(`https://api.example.com/search?q=${query}`);
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    };

    const { query, results, loading, error } = useSearch(searchFunction, '', 300);

    return {
      query,
      results,
      loading,
      error
    };
  }
};
</script>

6. <script setup> 语法中使用带防抖的搜索功能 Hook

<script setup> 语法中,使用带防抖的 useSearch Hook 也非常简洁。

<template>
  <div>
    <input v-model="query" placeholder="Search..." />
    <p v-if="loading">Loading...</p>
    <p v-else-if="error">Error: {{ error.message }}</p>
    <ul v-else>
      <li v-for="result in results" :key="result.id">{{ result.name }}</li>
    </ul>
  </div>
</template>

<script setup>
import { useSearch } from './useSearch';

const searchFunction = async (query) => {
  const response = await fetch(`https://api.example.com/search?q=${query}`);
  if (!response.ok) {
    throw new Error('Network response was not ok');
  }
  return response.json();
};

const { query, results, loading, error } = useSearch(searchFunction, '', 300);
</script>

总结

  • 通过自定义 Hook useSearch,你可以封装搜索逻辑,使其在多个组件中复用。
  • useSearch Hook 可以处理输入框的输入、触发搜索请求、管理加载状态和错误状态等。
  • 可以通过添加防抖功能来防止频繁触发搜索请求。
  • 在组件中,你可以像使用普通函数一样使用 useSearch Hook,返回的响应式数据和方法可以直接在模板中使用。
  • <script setup> 语法中,使用 useSearch Hook 更加简洁。
学在每日,进无止境!更多精彩内容请关注微信公众号。
原文出处: 内容由AI生成仅供参考,请勿使用于商业用途。如若转载请注明原文及出处。
出处地址:http://www.07sucai.com/tech/875.html
版权声明:本文来源地址若非本站均为转载,若侵害到您的权利,请及时联系我们,我们会在第一时间进行处理。
轻松 一刻
>