search-fix-summary.md 7.39 KB

搜索页面修复总结

修复时间

2026-01-31

修复的问题

🔴 问题 1: 清空关键词后显示错误的界面状态(已修复)

问题描述

  • 用户搜索后清空关键词,界面显示"初始状态"而不是"暂无搜索结果"
  • 这导致用户体验差,不知道自己曾经搜索过

根本原因

// ❌ 修复前
watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    hasSearched.value = true
  } else {
    hasSearched.value = false  // 这里会重置状态
  }
})

修复方案

// ✅ 修复后
watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    hasSearched.value = true
  }
  // 移除 else 分支,保持 hasSearched = true
})

修复内容

  1. ✅ 移除 watch 中的 else 分支(第 353-356 行)
  2. ✅ 移除 clearSearch 中的 hasSearched.value = false(第 324 行)
  3. ✅ 添加 isInitialState computed 属性(第 156-158 行)
  4. ✅ 更新模板条件判断(第 121 行)

修改的文件

1. src/pages/search/index.vue

修改 1: 添加 isInitialState computed 属性

/**
 * 是否显示初始状态
 * @description 只有在从未搜索过且没有关键词时才显示初始状态
 */
const isInitialState = computed(() => {
  return !hasSearched.value && !searchKeyword.value.trim()
})

修改 2: 更新 watch 逻辑

/**
 * 监听搜索关键词变化,实现实时搜索
 * @description 当用户输入关键词时,自动触发搜索,并标记"已搜索"状态
 */
watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    // ✅ 用户输入关键词时,标记为"已搜索"
    hasSearched.value = true
    console.log('[Search Watch] 实时搜索触发,关键词:', newVal)
    console.log('[Search Watch] 当前分类:', activeTabId.value)
    console.log('[Search Watch] 搜索结果数量:', searchResults.value.length)
    console.log('[Search Watch] hasSearched 设置为 true')
  }
  // ✅ 清空关键词时,不要重置 hasSearched
  // 这样可以保持"已搜索"状态,显示"暂无搜索结果"而不是"初始状态"
})

修改 3: 更新 clearSearch 函数

/**
 * 清空搜索
 * @description 清空搜索关键词,但保持 hasSearched 状态
 * 以显示"暂无搜索结果"而不是"初始状态"
 */
const clearSearch = () => {
  console.log('[Search Clear] 清空搜索关键词')
  searchKeyword.value = ''
  // ❌ 不要重置 hasSearched,保持"已搜索"状态
  // hasSearched.value = false
  listRenderKey.value += 1
  console.log('[Search Clear] hasSearched 保持为:', hasSearched.value)
}

修改 4: 更新模板条件判断

<!-- Empty State (已搜索但无结果) -->
<view v-else-if="hasSearched && searchResults.length === 0" class="flex flex-col items-center justify-center py-[120rpx]">
  <image
    class="w-[320rpx] h-[320rpx] mb-[40rpx]"
    src="https://picsum.photos/seed/empty/320/320"
    mode="aspectFit"
  />
  <view class="text-[#6B7280] text-[28rpx]">暂无搜索结果</view>
  <view class="text-[#9CA3AF] text-[24rpx] mt-[12rpx]">试试其他关键词吧</view>
</view>

<!-- Initial State (从未搜索过) -->
<view v-else-if="isInitialState" class="flex flex-col items-center justify-center py-[120rpx]">
  <IconFont name="search" class="text-gray-300 mb-[24rpx]" size="64" />
  <view class="text-[#6B7280] text-[28rpx]">搜索培训资料、案例、产品</view>
  <view class="text-[#9CA3AF] text-[24rpx] mt-[12rpx]">输入关键词开始搜索</view>
</view>

2. src/pages/search/index.test.js

修改 1: 移除未使用的导入

// ❌ 修复前
import { mount, flushPromises } from '@vue/test-utils'

// ✅ 修复后
import { mount } from '@vue/test-utils'

修改 2: 修复语法错误

// ❌ 修复前
await wrapper.vm.searchKeyword = '保险'

// ✅ 修复后
wrapper.vm.searchKeyword = '保险'
await wrapper.vm.$nextTick()

修改 3: 更新测试用例以反映修复后的行为

// ✅ 修复后:清空搜索关键词后 hasSearched 应该保持为 true
it('清空搜索关键词后 hasSearched 应该保持为 true', async () => {
  // 先执行搜索
  wrapper.vm.searchKeyword = '保险'
  await wrapper.vm.$nextTick()
  await wrapper.vm.handleSearch()
  expect(wrapper.vm.hasSearched).toBe(true)

  // 清空搜索
  await wrapper.vm.clearSearch()
  expect(wrapper.vm.searchKeyword).toBe('')
  // ✅ 修复后:hasSearched 应该保持 true
  expect(wrapper.vm.hasSearched).toBe(true)
})

修复后的行为

场景 1: 用户搜索后清空关键词

修复前

  1. 输入"保险"搜索 → 看到结果
  2. 清空输入框 → ❌ 显示"初始状态"(搜索图标)

修复后

  1. 输入"保险"搜索 → 看到结果
  2. 清空输入框 → ✅ 显示"暂无搜索结果"(空状态图)

场景 2: 用户首次进入页面

修复前:显示"初始状态" 修复后:✅ 显示"初始状态"(无变化,符合预期)

场景 3: 用户搜索后刷新页面

修复前:显示"初始状态" 修复后:✅ 显示"初始状态"(无变化,符合预期)


状态管理优化

新增状态变量

  • isInitialState (computed): 是否显示初始状态
    • true: 从未搜索过且没有关键词
    • false: 已经搜索过或有关键词

状态流转

初始状态 (isInitialState = true)
    ↓
用户输入关键词
    ↓
搜索状态 (hasSearched = true)
    ↓
清空关键词 → 保持"已搜索"状态,显示"暂无搜索结果"

测试建议

手动测试清单

  • 输入关键词,验证搜索结果正确
  • 清空关键词,验证显示"暂无搜索结果"(而非"初始状态")
  • 搜索后切换分类,验证结果数量正确更新
  • 在微信开发者工具中测试完整流程
  • 在真机上测试(如果有条件)

自动化测试

虽然项目中暂时没有配置 vitest,但测试文件已经编写完成,配置好测试环境后可以运行:

pnpm test src/pages/search/index.test.js

代码质量改进

添加的注释

  • ✅ 为 hasSearched 添加了详细说明
  • ✅ 为 isInitialState 添加了 JSDoc 注释
  • ✅ 为 watchclearSearch 添加了行为说明
  • ✅ 为模板条件判断添加了语义化的注释

改进的可读性

  • ✅ 使用更清晰的变量名 isInitialState
  • ✅ 模板条件判断更加明确
  • ✅ 状态流转逻辑更加清晰

相关文档


下一步建议

可选优化

  1. 添加防抖功能:避免频繁触发搜索请求 ```javascript import { useDebounceFn } from '@vueuse/core'

const debouncedSearch = useDebounceFn(() => { if (searchKeyword.value.trim()) { hasSearched.value = true } }, 300)

watch(searchKeyword, () => { debouncedSearch() })


2. **添加搜索历史**:记录用户搜索过的关键词
3. **添加搜索建议**:根据输入提供智能建议

### 性能优化
1. **虚拟滚动**:如果搜索结果很多,可以考虑使用虚拟滚动
2. **结果缓存**:缓存已搜索的结果,避免重复计算

---

**修复完成时间**: 2026-01-31
**修复者**: Claude Code
**测试状态**: 待配置测试环境后验证