一、案例介绍
本案例将展示Search组件的搜索联想功能和数据处理实现,通过一个知识库搜索系统的示例,展示如何处理复杂的搜索逻辑和数据交互。
二、代码实现
@Entry
@Component
struct SearchSuggestionExample {
@State searchText: string = ''
@State suggestions: Array<{
id: number,
keyword: string,
type: string,
weight: number
}> = []
@State searchResults: Array<{
id: number,
title: string,
content: string,
category: string,
tags: string[]
}> = []
@State isLoading: boolean = false
private searchCache: Map<string, any> = new Map()
private debounceTimer: number = -1
build() {
Column() {
// 搜索栏
Search({
value: this.searchText,
placeholder: '搜索知识库',
searchButton: '搜索'
})
.width('90%')
.height(40)
.backgroundColor('#FFFFFF')
.placeholderColor('#999999')
.placeholderFont({ size: 16 })
.borderRadius(20)
.margin({ top: 20, bottom: 10 })
.onChange((value: string) => {
this.searchText = value
this.debounceGetSuggestions(value)
})
.onSubmit((value: string) => {
this.performSearch(value)
})
.onClear(() => {
this.clearSearch()
})
if (this.isLoading) {
// 加载状态
LoadingProgress()
.width(24)
.height(24)
.margin(20)
} else if (this.suggestions.length > 0 && this.searchText.length > 0) {
// 搜索联想列表
List() {
ForEach(this.suggestions, (item) => {
ListItem() {
Row() {
Column() {
Text(item.keyword)
.fontSize(16)
.fontWeight(FontWeight.Medium)
Text(item.type)
.fontSize(12)
.fontColor('#999999')
.margin({ top: 4 })
}
.alignItems(HorizontalAlign.Start)
if (item.weight > 80) {
Text('热门')
.fontSize(12)
.fontColor('#FF4D4F')
.backgroundColor('#FFE8E8')
.padding({ left: 8, right: 8, top: 2, bottom: 2 })
.borderRadius(10)
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding(16)
.onClick(() => {
this.searchText = item.keyword
this.performSearch(item.keyword)
})
}
})
}
.width('90%')
.backgroundColor(Color.White)
.borderRadius(8)
} else if (this.searchResults.length > 0) {
// 搜索结果列表
List() {
ForEach(this.searchResults, (item) => {
ListItem() {
Column() {
Text(item.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 8 })
Text(item.content)
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 8 })
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Row() {
ForEach(item.tags, (tag: string) => {
Text(tag)
.fontSize(12)
.fontColor('#007DFF')
.backgroundColor('#E6F2FF')
.padding({ left: 8, right: 8, top: 2, bottom: 2 })
.borderRadius(10)
.margin({ right: 8 })
})
}
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.margin({ bottom: 8 })
}
})
}
.width('90%')
}
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
private debounceGetSuggestions(keyword: string) {
if (this.debounceTimer !== -1) {
clearTimeout(this.debounceTimer)
}
if (keyword.length === 0) {
this.suggestions = []
return
}
// 使用防抖处理联想请求
this.debounceTimer = setTimeout(() => {
this.getSuggestions(keyword)
}, 300)
}
private async getSuggestions(keyword: string) {
// 检查缓存
const cacheKey = `suggestion_${keyword}`
if (this.searchCache.has(cacheKey)) {
this.suggestions = this.searchCache.get(cacheKey)
return
}
this.isLoading = true
// 模拟异步请求
await new Promise(resolve => setTimeout(resolve, 500))
// 模拟联想数据
const suggestions = [
{ id: 1, keyword: `${keyword} 教程`, type: '文档', weight: 90 },
{ id: 2, keyword: `${keyword} 示例`, type: '代码', weight: 85 },
{ id: 3, keyword: `${keyword} 问题`, type: '问答', weight: 75 },
{ id: 4, keyword: `${keyword} 最佳实践`, type: '文章', weight: 70 }
]
// 更新缓存
this.searchCache.set(cacheKey, suggestions)
this.suggestions = suggestions
this.isLoading = false
}
private async performSearch(keyword: string) {
if (keyword.trim().length === 0) return
this.isLoading = true
this.suggestions = []
// 检查缓存
const cacheKey = `search_${keyword}`
if (this.searchCache.has(cacheKey)) {
this.searchResults = this.searchCache.get(cacheKey)
this.isLoading = false
return
}
// 模拟异步搜索
await new Promise(resolve => setTimeout(resolve, 1000))
// 模拟搜索结果
const results = [
{
id: 1,
title: `${keyword} 开发指南`,
content: '这是一份详细的开发指南,包含了完整的API文档和使用示例...',
category: '教程',
tags: ['入门', '文档']
},
{
id: 2,
title: `${keyword} 实战案例`,
content: '通过实际项目案例,深入讲解开发过程中的注意事项和最佳实践...',
category: '案例',
tags: ['进阶', '实战']
}
]
// 更新缓存
this.searchCache.set(cacheKey, results)
this.searchResults = results
this.isLoading = false
}
private clearSearch() {
this.searchText = ''
this.suggestions = []
this.searchResults = []
}
onDestroy() {
if (this.debounceTimer !== -1) {
clearTimeout(this.debounceTimer)
}
}
}
三、总结
本案例通过一个知识库搜索系统,展示了 Search 组件的搜索联想功能和数据处理实现。通过配置搜索框的基本属性(如占位符、搜索按钮文本等),实现了标准的搜索框界面。同时,通过自定义样式(如背景色、字体、圆角等),提升了搜索框的视觉效果。此外,通过事件监听(如 onChange、onSubmit、onClear),实现了实时搜索、提交搜索和清空搜索结果等功能