搜索框多种搜索

76 阅读4分钟

实现步骤概述

  1. 定义防抖函数

    • 创建一个名为 debounce 的函数,该函数接受两个参数:func 和 wait
    • func 是需要被防抖处理的函数,wait 是防抖等待的时间(毫秒)。
    • 函数内部使用 setTimeout 来实现防抖逻辑,确保在等待时间结束后才执行原函数。
  2. 修改Vue组件

    • 在组件的数据模型中定义所需的变量:query(输入框的值),suggestions(搜索建议列表),history(历史搜索记录列表)。
    • 在组件的 created 生命周期钩子中初始化历史搜索记录。
    • 使用防抖函数处理输入框的输入事件,减少不必要的搜索请求。
    • 在模板中添加输入框、搜索按钮、显示搜索建议和历史搜索记录的列表。
    • 实现处理输入事件的方法 onInput,用于发送请求获取搜索建议。
    • 实现方法 selectSuggestion 和 selectHistory,分别处理用户选择搜索建议和历史搜索记录的行为。
    • 实现方法 search,用于处理实际的搜索行为,更新历史搜索记录,并将其存储到本地存储中。
  3. 处理搜索建议

    • 当输入框的值大于一定长度时,调用防抖处理后的 onInput 方法,获取搜索建议。
    • 更新 suggestions 列表,显示搜索建议给用户。
  4. 处理历史搜索记录

    • 用户每次搜索后,更新历史搜索记录列表,并存储到浏览器的 localStorage 中。
    • 显示历史搜索记录列表供用户快速重复搜索。
  5. 优化用户体验

    • 使用防抖技术减少不必要的网络请求,提高应用性能。
    • 提供搜索建议和历史搜索记录,提高用户的搜索效率。

代码关键点

  • 防抖函数 (debounce):控制在一定时间内只执行一次函数。
  • 数据模型 (data):定义数据属性。
  • 生命周期钩子 (created):初始化历史搜索记录。
  • 输入事件处理 (onInput):发送请求获取搜索建议。
  • 选择搜索建议 (selectSuggestion):处理用户选择搜索建议的行为。
  • 选择历史搜索记录 (selectHistory):处理用户选择历史搜索记录的行为。
  • 执行搜索 (search):更新历史搜索记录并执行搜索操作。

1. 定义防抖函数

防抖函数用于控制在一定时间内只执行一次函数。这对于处理像键盘输入这样的高频事件非常有用,可以避免在短时间内触发过多的请求。

// 定义防抖函数
function debounce(func, wait) {
  let timeout; // 用于存储定时器ID
  return function() {
    const context = this; // 保存当前上下文
    const args = arguments; // 保存当前调用的所有参数
    clearTimeout(timeout); // 清除之前的定时器
    timeout = setTimeout(function() {
      // 设置新的定时器,在等待时间结束后执行原函数
      func.apply(context, args); // 使用保存的上下文和参数调用原函数
    }, wait); // 等待时间
  };
}

2. 创建一个通用的搜索组件

首先,我们创建一个名为 SearchBox.vue 的通用搜索组件, 接下来我们修改Vue组件以使用防抖函数,并实现搜索建议功能。

<template>
  <div class="advanced-search-box">
    <!-- 输入框 -->
    <input
      v-model="query"
      placeholder="搜索..."
      @input="debouncedOnInput"
      @keydown.enter="search"
    />
    <!-- 搜索按钮 -->
    <button @click="search">搜索</button>
    <!-- 显示搜索建议列表 -->
    <ul v-if="suggestions.length > 0">
      <li v-for="(suggestion, index) in suggestions" :key="index" @click="selectSuggestion(suggestion)">
        {{ suggestion }}
      </li>
    </ul>
    <!-- 显示历史搜索记录列表 -->
    <ul v-if="history.length > 0">
      <li v-for="(item, index) in history" :key="index" @click="selectHistory(item)">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 查询字符串
      query: '',
      // 搜索建议列表
      suggestions: [],
      // 历史搜索记录列表
      history: [],
    };
  },
  created() {
    // 使用防抖函数,设定300毫秒延迟
    this.debouncedOnInput = debounce(this.onInput, 300);
    
    // 初始化历史搜索记录
    this.history = JSON.parse(localStorage.getItem('searchHistory')) || [];
  },
  methods: {
    // 输入事件处理函数
    onInput(event) {
      this.suggestions = []; // 清空建议列表
      const inputValue = event.target.value;

      if (inputValue.length > 2) {
        // 发送请求获取搜索建议
        fetch(`/api/suggestions?query=${encodeURIComponent(inputValue)}`)
          .then(response => response.json())
          .then(data => {
            this.suggestions = data; // 更新搜索建议列表
          })
          .catch(error => {
            console.error('Error fetching search suggestions:', error);
          });
      }
    },
    // 防抖后的onInput函数
    debouncedOnInput: null,
    // 选择搜索建议时触发
    selectSuggestion(suggestion) {
      this.query = suggestion; // 将选中的建议作为查询字符串
      this.suggestions = []; // 清空建议列表
      this.search(); // 执行搜索
    },
    // 选择历史搜索记录时触发
    selectHistory(item) {
      this.query = item; // 将选中的历史记录作为查询字符串
      this.search(); // 执行搜索
    },
    // 搜索按钮点击时触发
    search() {
      const searchItem = this.query;
      
      // 更新历史搜索记录
      if (!this.history.includes(searchItem)) {
        this.history.unshift(searchItem); // 将查询字符串添加到历史记录的最前面
        this.history = this.history.slice(0, 10); // 只保留最近10条记录
        localStorage.setItem('searchHistory', JSON.stringify(this.history)); // 存储历史记录
      }

      console.log(`执行搜索: ${this.query}`); // 打印搜索关键词
      // 这里可以发送请求到后端执行搜索逻辑
    },
  },
};
</script>

<style scoped>
/* ...styles unchanged... */
</style>

3. 引入组件并使用

现在我们需要在主应用文件 App.vue 中引入这个组件,并将其添加到模板中:

<template>
  <div id="app">
    <SearchBox />
  </div>
</template>

<script>
import SearchBox from './components/SearchBox.vue';

export default {
  components: {
    SearchBox,
  },
};
</script>

代码解析

1. 防抖函数

  • debounce: 用于控制在一定时间内只执行一次函数。

    • timeout: 用于存储定时器ID。
    • context: 保存当前上下文。
    • args: 保存当前调用的所有参数。
    • clearTimeout(timeout) : 清除之前的定时器。
    • setTimeout: 设置新的定时器,在等待时间结束后执行原函数。

2. Vue组件

  • data: 定义数据属性。

    • query: 查询字符串。
    • suggestions: 搜索建议列表。
    • history: 历史搜索记录列表。
  • created: 组件创建完成时执行。

    • debouncedOnInput: 防抖后的onInput函数。
    • history: 初始化历史搜索记录。
  • methods:

    • onInput: 输入事件处理函数。

      • inputValue: 获取输入框的值。
      • fetch: 发送请求获取搜索建议。
    • debouncedOnInput: 防抖后的onInput函数。

    • selectSuggestion: 选择搜索建议时触发。

    • selectHistory: 选择历史搜索记录时触发。

    • search: 搜索按钮点击时触发。

      • history: 更新历史搜索记录。
      • localStorage: 存储历史记录。