HarmonyOS 鸿蒙Next中如何使用Search组件实现搜索功能?如何保存搜索历史?

HarmonyOS 鸿蒙Next中如何使用Search组件实现搜索功能?如何保存搜索历史? 我需要实现一个搜索页面,Search 组件如何使用?如何保存和显示搜索历史?

3 回复

实现思路:

  1. 使用 Search 组件,通过 onSubmit 处理搜索提交:
Search({ value: this.keyword, placeholder: '搜索...' })
  .onSubmit((value: string) => {
    this.doSearch(value);
  })
  .onChange((value: string) => {
    this.keyword = value;
  })
  1. 使用 Preferences 保存搜索历史:
async saveToHistory(keyword: string) {
  const history = this.searchHistory.filter(h => h !== keyword);
  history.unshift(keyword);
  this.searchHistory = history.slice(0, 10);
  await storageUtil.putObject('searchHistory', this.searchHistory);
}
  1. 对数据进行关键词过滤:
this.searchResults = this.allData.filter(item =>
  item.title.includes(keyword) || item.desc.includes(keyword)
);
  1. 完整示例代码:
@Entry
@Component
struct SearchPage {
  @State keyword: string = '';
  @State searchHistory: string[] = [];
  @State searchResults: DataItem[] = [];
  @State isSearching: boolean = false;

  private allData: DataItem[] = [
    { id: '1', title: '苹果手机', desc: 'iPhone 15 Pro' },
    { id: '2', title: '华为手机', desc: 'Mate 60 Pro' },
    { id: '3', title: '小米手机', desc: 'Xiaomi 14' }
  ];

  async aboutToAppear() {
    this.searchHistory = await storageUtil.getObject<string[]>('searchHistory', []);
  }

  async doSearch(keyword: string) {
    if (!keyword.trim()) return;

    this.isSearching = true;
    this.keyword = keyword;
    await this.saveToHistory(keyword);

    // 过滤数据
    this.searchResults = this.allData.filter(item =>
      item.title.includes(keyword) || item.desc.includes(keyword)
    );
    this.isSearching = false;
  }

  async saveToHistory(keyword: string) {
    const history = this.searchHistory.filter(h => h !== keyword);
    history.unshift(keyword);
    this.searchHistory = history.slice(0, 10);
    await storageUtil.putObject('searchHistory', this.searchHistory);
  }

  async clearHistory() {
    this.searchHistory = [];
    await storageUtil.delete('searchHistory');
  }

  build() {
    Column() {
      // 搜索框
      Search({ value: this.keyword, placeholder: '搜索...' })
        .width('100%')
        .height(40)
        .onChange((value: string) => {
          this.keyword = value;
          if (!value) this.searchResults = [];
        })
        .onSubmit((value: string) => this.doSearch(value))

      // 搜索历史
      if (this.searchHistory.length > 0 && !this.keyword) {
        Column() {
          Row() {
            Text('搜索历史').fontSize(14).fontColor('#666')
            Blank()
            Text('清空').fontSize(12).fontColor('#999')
              .onClick(() => this.clearHistory())
          }
          .width('100%')
          .margin({ bottom: 8 })

          Flex({ wrap: FlexWrap.Wrap }) {
            ForEach(this.searchHistory, (item: string) => {
              Text(item)
                .fontSize(12)
                .padding({ left: 12, right: 12, top: 6, bottom: 6 })
                .backgroundColor('#F0F0F0')
                .borderRadius(16)
                .margin(4)
                .onClick(() => this.doSearch(item))
            })
          }
        }
        .padding(16)
      }

      // 搜索结果
      if (this.isSearching) {
        LoadingProgress().width(40).margin({ top: 40 })
      } else if (this.searchResults.length > 0) {
        List({ space: 8 }) {
          ForEach(this.searchResults, (item: DataItem) => {
            ListItem() {
              Column() {
                Text(item.title).fontSize(16)
                Text(item.desc).fontSize(12).fontColor('#666')
              }
              .alignItems(HorizontalAlign.Start)
              .padding(12)
            }
          })
        }
        .padding(16)
      } else if (this.keyword) {
        Text('暂无搜索结果').fontColor('#999').margin({ top: 40 })
      }
    }
    .width('100%')
    .height('100%')
  }
}

interface DataItem {
  id: string;
  title: string;
  desc: string;
}

更多关于HarmonyOS 鸿蒙Next中如何使用Search组件实现搜索功能?如何保存搜索历史?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用Search组件实现搜索功能:在ArkUI中引入Search组件,通过onSubmit事件处理搜索提交逻辑,使用onChange监听输入内容变化。

保存搜索历史:通过PreferencesRDB持久化存储搜索记录。在onSubmit事件中,将搜索关键词保存至本地数据库,并在需要时查询展示历史列表。

在HarmonyOS Next中,使用Search组件实现搜索功能并保存历史记录,可以按以下步骤操作:

1. 使用Search组件

Search是ArkUI的基础组件,用于创建搜索框。基本用法如下:

@Entry
@Component
struct SearchExample {
  @State searchText: string = ''

  build() {
    Column() {
      Search({
        placeholder: '请输入关键词',
        controller: this.searchController
      })
      .onChange((value: string) => {
        this.searchText = value
      })
      .onSubmit((value: string) => {
        // 处理搜索提交
        this.performSearch(value)
      })
      .width('100%')
    }
  }

  performSearch(keyword: string) {
    // 执行搜索逻辑
    console.log(`搜索关键词: ${keyword}`)
  }
}

2. 保存搜索历史

建议使用轻量级存储(Preferences)保存搜索历史:

import preferences from '@ohos.data.preferences'

class SearchHistoryManager {
  private static readonly KEY_HISTORY = 'search_history'
  private static readonly MAX_HISTORY = 10

  // 保存搜索记录
  static async saveSearchKeyword(keyword: string): Promise<void> {
    try {
      const prefs = await preferences.getPreferences(this.getContext(), 'search_history')
      let history = await prefs.get(this.KEY_HISTORY, '[]')
      let historyArray = JSON.parse(history)
      
      // 去重并限制数量
      historyArray = historyArray.filter((item: string) => item !== keyword)
      historyArray.unshift(keyword)
      historyArray = historyArray.slice(0, this.MAX_HISTORY)
      
      await prefs.put(this.KEY_HISTORY, JSON.stringify(historyArray))
      await prefs.flush()
    } catch (error) {
      console.error('保存搜索历史失败:', error)
    }
  }

  // 获取搜索历史
  static async getSearchHistory(): Promise<string[]> {
    try {
      const prefs = await preferences.getPreferences(this.getContext(), 'search_history')
      const history = await prefs.get(this.KEY_HISTORY, '[]')
      return JSON.parse(history)
    } catch (error) {
      console.error('获取搜索历史失败:', error)
      return []
    }
  }

  // 清空搜索历史
  static async clearSearchHistory(): Promise<void> {
    try {
      const prefs = await preferences.getPreferences(this.getContext(), 'search_history')
      await prefs.delete(this.KEY_HISTORY)
      await prefs.flush()
    } catch (error) {
      console.error('清空搜索历史失败:', error)
    }
  }
}

3. 显示搜索历史

在Search组件下方显示历史记录列表:

@Component
struct SearchHistoryList {
  @State historyList: string[] = []

  build() {
    Column() {
      if (this.historyList.length > 0) {
        List() {
          ForEach(this.historyList, (item: string) => {
            ListItem() {
              Text(item)
                .fontSize(16)
                .padding(10)
            }
            .onClick(() => {
              // 点击历史记录重新搜索
              this.onHistoryItemClick(item)
            })
          })
        }
      } else {
        Text('暂无搜索历史')
          .fontSize(14)
          .fontColor(Color.Gray)
      }
    }
  }

  // 加载历史记录
  async aboutToAppear() {
    this.historyList = await SearchHistoryManager.getSearchHistory()
  }
}

4. 完整集成示例

@Entry
@Component
struct SearchPage {
  @State searchText: string = ''
  @State searchHistory: string[] = []
  private searchController: SearchController = new SearchController()

  build() {
    Column() {
      // 搜索框
      Search({
        placeholder: '搜索...',
        controller: this.searchController
      })
      .onChange((value: string) => {
        this.searchText = value
      })
      .onSubmit(async (value: string) => {
        if (value.trim()) {
          await SearchHistoryManager.saveSearchKeyword(value)
          await this.loadSearchHistory()
          this.performSearch(value)
        }
      })

      // 历史记录
      SearchHistoryList({ historyList: this.searchHistory })
    }
  }

  async loadSearchHistory() {
    this.searchHistory = await SearchHistoryManager.getSearchHistory()
  }

  async aboutToAppear() {
    await this.loadSearchHistory()
  }
}

关键点说明:

  1. Search组件事件onChange监听输入变化,onSubmit处理搜索提交
  2. 数据存储:使用Preferences持久化存储,适合保存少量历史数据
  3. 历史记录管理:限制记录数量,避免重复,新的记录放在前面
  4. 性能考虑:历史记录数量建议控制在10-20条以内

这样实现后,用户每次搜索时会自动保存记录,并在下次打开搜索页面时显示历史记录。点击历史记录可以快速重新搜索。

回到顶部