You need to sign in or sign up before continuing.
search-problems-analysis.md 7.44 KB

搜索页面问题分析报告

📋 问题概述

分析 src/pages/search/index.vue 的搜索功能,发现以下关键问题。


🔴 问题 1: 清空关键词后的状态混乱

问题描述

用户搜索后,如果清空搜索关键词,会看到错误的界面状态

复现步骤

  1. 输入关键词"保险",点击搜索
  2. 看到搜索结果(假设有 50 条)
  3. 删除输入框中的关键词(清空)
  4. 错误:界面显示"初始状态"(搜索图标 + "输入关键词开始搜索")
  5. 期望:界面应该显示"暂无搜索结果"(空状态图 + "暂无搜索结果")

根本原因

代码第 344-353 行的 watch(searchKeyword, ...) 逻辑有问题:

watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    hasSearched.value = true  // ✅ 有关键词时,设置 hasSearched = true
  } else {
    hasSearched.value = false  // ❌ 没有关键词时,重置 hasSearched = false
  }
})

问题

  • 当用户清空关键词时,hasSearched 被重置为 false
  • 导致模板第 121-125 行的"初始状态"被渲染: vue <view v-else 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>

用户影响

  • 用户体验差:清空关键词后,不知道自己之前搜索过
  • 逻辑不连贯:已经搜索过,应该保持"已搜索状态"

修复方案

需要区分两种情况:

  1. 从未搜索过:显示"初始状态"(引导用户搜索)
  2. 搜索过但清空了关键词:显示"暂无搜索结果"(提示用户没有结果)
// 新增状态:记录是否曾经搜索过
const hasSearchedOnce = ref(false)

watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    hasSearched.value = true
    hasSearchedOnce.value = true  // ✅ 标记已经搜索过
  } else {
    // ❌ 不要重置 hasSearched
    // hasSearched.value = false  // 删除这行

    // ✅ 保持 hasSearched 不变,让 computed 返回空结果
  }
})

🟡 问题 2: 模板条件判断逻辑不清晰

问题描述

模板第 49-125 行的条件判断逻辑复杂且容易出错。

当前逻辑

<!-- 有结果 -->
<view v-if="searchResults.length > 0">
  <!-- 显示结果 -->
</view>

<!-- 空结果(但 hasSearched = true) -->
<view v-else-if="hasSearched">
  <!-- 显示空状态 -->
</view>

<!-- 初始状态(hasSearched = false) -->
<view v-else>
  <!-- 显示初始状态 -->
</view>

问题

  • hasSearched 的语义不清晰:表示"是否搜索过"还是"应该显示结果"?
  • hasSearched 被多处修改,难以维护

修复方案

使用更清晰的变量名和逻辑:

// 方案 1:使用两个状态变量
const isInitialState = ref(true)  // 是否初始状态
const searchResults = ref([])

// 方案 2:使用枚举状态
const searchState = ref('idle')  // 'idle' | 'searching' | 'results' | 'empty'

🟡 问题 3: 切换分类时的状态不一致

问题描述

用户搜索后切换分类,可能看到错误的结果数量。

复现步骤

  1. 在"全部"分类搜索"保险"(假设有 50 条结果)
  2. 切换到"产品"分类(假设有 30 条结果)
  3. 切换到"资料"分类(假设有 20 条结果)

预期行为

  • 每次切换分类,结果数量应该正确更新

实际行为

  • 需要验证:listRenderKey 是否正确触发了重新渲染
  • 需要验证:searchResults computed 是否正确响应 activeTabId 的变化

潜在问题

第 51 行的 :key="listRenderKey" 用于强制重新渲染,但这是不优雅的做法:

<view
  v-if="searchResults.length > 0"
  :key="listRenderKey"  // ⚠️ 通过改变 key 强制重新渲染
>

更好的方案

  • 依赖 Vue 的响应式系统,自动重新计算 searchResults
  • 不需要手动维护 listRenderKey

🟢 问题 4: 实时搜索 vs 手动搜索冲突

问题描述

watch(searchKeyword) 实现了实时搜索,但 handleSearch() 也实现了手动搜索,两者可能产生冲突。

当前实现

// 实时搜索(第 344 行)
watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    hasSearched.value = true
  }
})

// 手动搜索(第 292 行)
const handleSearch = () => {
  if (searchKeyword.value.trim()) {
    hasSearched.value = true
  }
}

冲突点

  • 用户输入"保" → 实时搜索触发 → hasSearched = true
  • 用户继续输入"保险" → 实时搜索再次触发 → hasSearched = true
  • 用户点击搜索按钮 → 手动搜索触发 → hasSearched = true(冗余)

建议

  1. 只保留实时搜索:移除 handleSearch 中的 hasSearched 设置
  2. 或者只保留手动搜索:移除 watch(searchKeyword) 中的逻辑
  3. 或者明确区分
    • 输入时:只更新关键词,不设置 hasSearched
    • 点击搜索按钮时:才设置 hasSearched = true

📊 测试建议

手动测试清单

  • 输入关键词,验证搜索结果正确
  • 清空关键词,验证显示"暂无搜索结果"(而非"初始状态")
  • 搜索后切换分类,验证结果数量正确更新
  • 清空关键词后切换分类,验证显示正确
  • 快速输入和删除关键词,验证不出现闪烁或错误

自动化测试

运行测试文件:

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

🔧 推荐修复方案

方案 1: 最小改动(快速修复)

只修复问题 1,改动最小:

// 第 344-354 行
watch(searchKeyword, (newVal) => {
  if (newVal.trim()) {
    hasSearched.value = true
  }
  // ❌ 删除 else 分支
  // else {
  //   hasSearched.value = false
  // }
})

影响

  • ✅ 清空关键词后,hasSearched 保持 true
  • ✅ 显示"暂无搜索结果"(而非"初始状态")
  • ⚠️ 但用户刷新页面后,仍然显示初始状态(符合预期)

方案 2: 重构状态管理(推荐)

使用更清晰的状态变量:

// 搜索状态枚举
const SearchState = {
  IDLE: 'idle',           // 初始状态(从未搜索)
  SEARCHING: 'searching', // 搜索中
  RESULTS: 'results',     // 有结果
  EMPTY: 'empty'          // 无结果
}

const searchState = ref(SearchState.IDLE)
const searchKeyword = ref('')

// 计算属性:根据搜索状态和结果数量返回应该显示的状态
const displayState = computed(() => {
  if (!searchKeyword.value.trim() && searchState.value === SearchState.IDLE) {
    return 'initial'
  }

  if (searchResults.value.length > 0) {
    return 'results'
  }

  return 'empty'
})

📝 总结

主要问题

  1. 清空关键词后显示错误的界面状态(🔴 高优先级)
  2. 模板条件判断逻辑不清晰(🟡 中优先级)
  3. 切换分类时的状态不一致(🟡 中优先级)
  4. 实时搜索 vs 手动搜索冲突(🟢 低优先级)

推荐行动

  1. 立即修复:问题 1(使用方案 1)
  2. 考虑重构:问题 2(使用方案 2)
  3. 验证测试:确保所有测试场景通过
  4. 用户测试:邀请真实用户测试搜索流程

生成时间: 2026-01-31 分析工具: Claude Code 测试文件: index.test.js