一.使用 <transition> 和 <transition-group> 实现动画效果
<transition-group>
是 Vue 的一个内置组件,用于处理多个元素或组件的进入/离开过渡。不同于<transition>
,它适用于列表,其中每个列表项都可以单独进行过渡动画
二.computed 计算属性
computed
被用来创建一个计算属性historyTags
。计算属性是基于响应式依赖的数据进行计算的属性,只有当其依赖的数据发生变化时,计算属性的值才会重新计算。
三.watch 监听属性
watch
函数被用来监听 searchValue
引用的变化。当 searchValue
发生变化时,watch
函数会执行一个回调函数,该回调函数使用 useDebounce
来实现防抖功能。这意味着实际的搜索逻辑只会在用户停止输入一段时间后执行,而不是每次输入变化时都执行。
- 使用axios实例发送业务请求
- mock 请求
- 展示切换动画
四.搜索框输入文字,自动发送请求
1. 监听搜索输入 (searchValue
)
使用 Vue 的 watch
函数监听 searchValue
的变化。这意味着每当用户在搜索框中输入时,searchValue
的值会发生变化,从而触发 watch
的回调函数。
watch(
searchValue,
useDebounce<string>(nv => {
// 搜索逻辑
}, 1000)
);
2. 使用防抖技术 (useDebounce
)
useDebounce
函数用于在用户停止输入一段时间(例如 1000 毫秒)后才执行搜索逻辑,而不是每次输入变化时都执行。
useDebounce<string>
接受一个回调函数和延迟时间作为参数。- 在此示例中,如果用户在 1000 毫秒内连续输入,之前的输入将不会触发搜索,只有在用户停止输入后 1000 毫秒内没有新的输入时,才会执行搜索。
3. 执行搜索操作 (onSearch
)
在 useDebounce
的回调函数中执行实际的搜索操作。回调函数会检查当前的搜索值 (nv
),并根据该值调用 onSearch
函数。
useDebounce<string>(nv => {
if (!nv) {
searchResult.value = [];
return;
} else {
onSearch(nv);
}
}, 1000)
- 如果输入值为空,清空搜索结果。
- 如果输入值不为空,调用
onSearch
函数,并将当前输入值作为参数传递。
4. onSearch
函数
onSearch
函数处理实际的搜索逻辑,通常包括发送 API 请求并处理响应。
const onSearch = async (v?: string | number) => {
try {
searchState.value = DOING;
const { list } = await fetchSearchData(v as string);
searchResult.value = list;
} finally {
searchState.value = DONE;
}
};
- 设置搜索状态为进行中 (
DOING
)。 - 发送搜索请求并等待结果。
- 更新搜索结果 (
searchResult
)。 - 更改搜索状态为完成 (
DONE
)。
五、搜索状态维护
逻辑:
1. 搜索状态变量
searchValue
: 存储当前的搜索输入。searchResult
: 存储搜索结果。searchState
: 表示当前搜索的状态,可以是初始化(INIT
)、进行中(DOING
)和完成(DONE
)。
2. 搜索逻辑
onSearch
: 异步函数,用于处理搜索逻辑。在搜索开始时设置状态为DOING
,完成后设置为DONE
。onTagClick
: 当用户点击历史标签时触发的函数,将标签值设置为当前搜索输入并执行搜索
3. 防抖处理
- 使用
watch
和useDebounce
,监视searchValue
的变化。当用户输入时,仅在停止输入一段时间(1000毫秒)后触发搜索,避免过于频繁的请求。
4. 模板渲染
- 根据
searchValue
的存在与否显示历史搜索标签或搜索结果。 - 在搜索进行中时显示一个加载提示。
- 当搜索完成后,根据
searchResult
的内容显示搜索结果。
5. 样式
- 使用 SCSS 定义了组件的样式,包括历史标签和搜索结果的样式。
- 历史搜索展示,点击
- 历史搜索后发送请求历史搜索更多切换动画
六、防抖节流解决
- 短时间内多次发送请求,造成返回结果的不正确
- 发送无用的请求,占用资源
七、搜索结果展示
-
条件渲染 (
v-if
/v-else
):- 使用
v-if="searchState === DONE"
来判断是否展示搜索结果。只有当搜索状态为DONE
时,搜索结果区域才显示。 - 使用
v-if="searchState === DOING"
来显示一个加载指示,例如“正在搜索”。 - 使用
v-if="searchResult.length"
来检查是否有搜索结果。如果有结果,展示这些结果。 - 使用
v-if="!searchResult.length"
来处理无结果的情况,显示如“暂无推荐”的消息。
- 使用
-
列表渲染 (
v-for
):- 使用
v-for="v in searchResult"
来循环遍历searchResult
数组中的每个搜索结果项。 - 对于每个搜索结果项
v
,展示其label
和resultCount
。
- 使用
-
展示搜索结果:
- 使用
{{ v.label }}
和{{ v.resultCount }}
来展示每个搜索结果项的标签和结果数。 - 使用
VanIcon
组件来展示搜索图标。
- 使用
总结
此组件中的搜索结果展示逻辑体现了 Vue 的核心特性,如响应式数据绑定、条件渲染和列表渲染。通过这些特性,组件能够根据当前的搜索状态和结果动态更新 UI,提供丰富的用户体验。这种方式确保了当搜索状态或结果发生变化时,用户界面能够自动且适当地响应这些变化。
<template>
<!-- ... 其他部分 ... -->
<div v-if="searchState === DONE" class="search-view__result">
<div class="searching" v-if="searchState === DOING">~正在搜索~</div>
<template v-if="searchResult.length">
<div class="result-item" v-for="v in searchResult" :key="v.label">
<VanIcon name="search"></VanIcon>
<div class="name">{{ v.label }}</div>
<div class="count">约{{ v.resultCount }}个结果</div>
</div>
</template>
<div class="no-result" v-if="!searchResult.length">~暂无推荐~</div>
</div>
</template>