fix: 搜索建议动画不连贯

This commit is contained in:
imsyy 2023-07-29 11:25:40 +08:00
parent 83fcfa7a01
commit 6084f75913
5 changed files with 116 additions and 146 deletions

View File

@ -11,7 +11,7 @@
> 由于 `CDN` 缓存原因,查看最新效果可能需要 `Ctrl` + `F5` 强制刷新浏览器缓存
- [Snavigation](https://nav.imsyy.top)
- [Snavigation Dev](https://snavigation.vercel.app)
- [Snavigation Dev](https://snavigation-git-dev-imsyy.vercel.app/)
### 功能

View File

@ -31,8 +31,8 @@
</div>
</div>
<!-- 搜索建议 -->
<SearchSuggestions
ref="searchSuggestionsRef"
<Suggestions
ref="suggestionsRef"
:keyWord="inputValue"
@toSearch="toSearch"
/>
@ -42,7 +42,7 @@
<script setup>
import { ref, onMounted } from "vue";
import { statusStore, setStore } from "@/stores";
import SearchSuggestions from "@/components/SearchSuggestions.vue";
import Suggestions from "@/components/Suggestions.vue";
const set = setStore();
const status = statusStore();
@ -57,7 +57,7 @@ const inputClickable = ref(true);
const inputValue = ref("");
//
const searchSuggestionsRef = ref(null);
const suggestionsRef = ref(null);
//
const closeSearchInput = () => {
@ -135,7 +135,7 @@ const pressKeyboard = (event) => {
// 13
if (keyCode === 13) toSearch();
//
searchSuggestionsRef.value?.keyboardEvents(keyCode, event);
suggestionsRef.value?.keyboardEvents(keyCode, event);
};
onMounted(() => {

View File

@ -1,20 +1,65 @@
<template>
<Transition name="fadeUp" mode="out-in">
<Transition name="fadeDown" mode="out-in">
<div
v-if="
set.showSuggestions &&
status.siteStatus === 'focus' &&
searchKeyword !== null
"
class="search-suggestions"
:style="{
height: suggestionsHeights !== 0 ? `${suggestionsHeights}px` : 'auto',
}"
class="suggestions"
:style="{ height: `${suggestionsHeights}px` }"
>
<!-- 快捷操作 -->
<Transition
name="fade"
mode="out-in"
@after-enter="changeSuggestionsHeights"
@after-leave="changeSuggestionsHeights"
>
<!-- 搜索建议 -->
<Transition name="fade" mode="out-in">
<div
v-show="
v-if="searchKeyword !== null"
class="special-result"
ref="specialallResultsRef"
>
<!-- 快捷翻译 -->
<div
v-if="searchKeywordType === 'text'"
class="s-result"
@click="toSearch(keyWord, 2)"
>
<SvgIcon iconName="icon-translation" />
<span class="text">快捷翻译{{ keyWord }}</span>
</div>
<!-- 直接访问 -->
<div
v-if="searchKeywordType !== 'text'"
class="s-result"
@click="
toSearch(searchKeyword, searchKeywordType === 'email' ? 3 : 4)
"
>
<SvgIcon
:iconName="`icon-${
searchKeywordType === 'email' ? 'email' : 'link'
}`"
/>
<span class="text">
{{
searchKeywordType === "email" ? "发送邮件至" : "直接访问"
}}{{ searchKeyword }}
</span>
</div>
</div>
</Transition>
<!-- 搜索建议 -->
<Transition
name="fade"
mode="out-in"
@after-enter="changeSuggestionsHeights"
@after-leave="changeSuggestionsHeights"
>
<div
v-if="
searchKeyword !== null &&
searchKeywordType === 'text' &&
searchSuggestionsData[0]
@ -22,12 +67,6 @@
class="all-result"
ref="allResultsRef"
>
<!-- 快捷翻译 -->
<div class="translation" @click="toSearch(searchKeyword, 2)">
<SvgIcon iconName="icon-translation" />
<span class="text">快捷翻译{{ searchKeyword }}</span>
</div>
<!-- 建议 -->
<div
v-for="item in searchSuggestionsData"
class="s-result"
@ -39,47 +78,6 @@
</div>
</div>
</Transition>
<!-- 无搜索建议 -->
<Transition name="fade" mode="out-in">
<div
v-show="searchKeywordType === 'text' && !hasSuggestions"
class="no-result"
>
<SvgIcon iconName="icon-found" className="not-found" />
<div class="all-text">
<span class="text">暂无搜索建议</span>
<span class="tip">请尝试其他关键词</span>
</div>
</div>
</Transition>
<!-- 特殊类型 -->
<Transition name="fade" mode="out-in">
<div
v-show="searchKeywordType !== 'text'"
class="special-result"
ref="specialResultsRef"
>
<!-- 直接访问 -->
<div
class="s-result"
@click="
toSearch(searchKeyword, searchKeywordType === 'email' ? 3 : 4)
"
>
<SvgIcon iconName="icon-link" />
<span class="text">
{{
searchKeywordType === "email" ? "发送邮件至" : "直接访问"
}}{{ searchKeyword }}
</span>
</div>
<!-- 直接搜索 -->
<div class="s-result" @click="toSearch(searchKeyword, 1)">
<SvgIcon iconName="icon-search" />
<span class="text">搜索{{ searchKeyword }}</span>
</div>
</div>
</Transition>
</div>
</Transition>
</template>
@ -101,11 +99,9 @@ const searchKeyword = ref(null);
const searchKeywordType = ref("text");
//
const searchSuggestionsData = ref([]);
//
const hasSuggestions = ref(true);
//
const specialallResultsRef = ref(null);
const allResultsRef = ref(null);
const specialResultsRef = ref(null);
//
const suggestionsHeights = ref(0);
//
@ -120,45 +116,32 @@ const props = defineProps({
//
const keywordsSearch = debounce((val) => {
const searchValue = val?.trim();
//
if (!searchValue || searchValue === "") {
searchKeyword.value = null;
return false;
}
//
searchKeyword.value = searchValue;
//
searchKeywordType.value = identifyInput(searchValue);
//
if (searchKeywordType.value === "text") {
if (searchValue) {
if (searchKeyword.value && searchKeywordType.value === "text") {
console.log(val + "的搜索建议");
//
searchSuggestionsData.value = [];
getSearchSuggestions(searchValue)
.then((res) => {
console.log(res);
//
hasSuggestions.value = res[0] ? true : false;
//
searchSuggestionsData.value = Array.from(res);
//
//
nextTick(() => {
const height = allResultsRef.value?.offsetHeight;
suggestionsHeights.value = res[0] ? height : 130;
changeSuggestionsHeights();
});
})
.catch((error) => {
//
searchSuggestionsData.value = [];
console.error("处理搜索建议发生错误:", error);
});
} else {
searchKeyword.value = null;
hasSuggestions.value = true;
suggestionsHeights.value = 0;
}
}
//
else {
hasSuggestions.value = true;
//
nextTick(() => {
const height = specialResultsRef.value?.offsetHeight;
suggestionsHeights.value = height ?? 62;
});
}
}, 300);
@ -171,7 +154,7 @@ const keyboardEvents = (keyCode, event) => {
if (keyCode === 38 || keyCode === 40) {
//
event.preventDefault();
if (mainInput && allResultsRef.value && hasSuggestions.value) {
if (mainInput && allResultsRef.value && searchSuggestionsData.value[0]) {
const suggestionItems =
allResultsRef.value.querySelectorAll(".s-result");
if (suggestionItems.length > 0) {
@ -208,6 +191,18 @@ const keyboardEvents = (keyCode, event) => {
}
};
//
const changeSuggestionsHeights = () => {
try {
const allResultsHeight = allResultsRef.value?.offsetHeight;
const specialallResultsHeight = specialallResultsRef.value?.offsetHeight;
suggestionsHeights.value =
(specialallResultsHeight || 0) + (allResultsHeight || 0);
} catch (error) {
console.error("计算高度时出现错误:" + error);
}
};
//
const toSearch = (val, type = 1) => {
emit("toSearch", val, type);
@ -216,7 +211,14 @@ const toSearch = (val, type = 1) => {
//
watch(
() => props.keyWord,
(val) => keywordsSearch(val)
(val) => {
//
searchSuggestionsData.value = [];
//
searchKeywordType.value = identifyInput(val);
//
keywordsSearch(val);
}
);
//
@ -224,7 +226,7 @@ defineExpose({ keyboardEvents });
</script>
<style lang="scss" scoped>
.search-suggestions {
.suggestions {
position: absolute;
top: 0;
left: 0;
@ -233,13 +235,12 @@ defineExpose({ keyboardEvents });
overflow-y: hidden;
color: var(--main-text-color);
background-color: var(--main-background-light-color);
backdrop-filter: blur(10px);
backdrop-filter: blur(30px) saturate(1.25);
border-radius: 16px;
transition: height 0.25s ease, opacity 0.3s ease, transform 0.3s ease;
transition: height 0.2s ease, opacity 0.3s ease, transform 0.3s ease;
.all-result,
.special-result {
.s-result,
.translation {
.s-result {
cursor: pointer;
box-sizing: border-box;
display: flex;
@ -263,37 +264,6 @@ defineExpose({ keyboardEvents });
background-color: var(--main-background-light-color);
padding-left: 18px;
}
&:first-child {
border-radius: 16px 16px 0 0;
}
&:last-child {
border-radius: 0 0 16px 16px;
}
}
}
.no-result {
width: 100%;
height: 130px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.not-found {
font-size: 32px;
margin-bottom: 8px;
}
.all-text {
display: flex;
flex-direction: column;
.text {
font-size: 18px;
display: inline-block;
margin-bottom: 6px;
}
.tip {
font-size: 14px;
opacity: 0.8;
}
}
}
}

View File

@ -44,15 +44,15 @@ body {
opacity: 0;
}
.fadeUp-enter-active,
.fadeUp-leave-active {
.fadeDown-enter-active,
.fadeDown-leave-active {
transition: opacity 0.3s ease, transform 0.3s ease;
}
.fadeUp-enter-from,
.fadeUp-leave-to {
.fadeDown-enter-from,
.fadeDown-leave-to {
opacity: 0;
transform: translateY(10px);
transform: translateY(-10px);
}
.show-enter-active,

File diff suppressed because one or more lines are too long