refactor: 重构 SearchMenu 组件结构

This commit is contained in:
pany 2024-11-23 00:04:43 +08:00
parent b18bf9d4b5
commit ff4ae8ba5b
4 changed files with 20 additions and 18 deletions

View File

@ -8,8 +8,8 @@ import { ElMessage } from "element-plus"
import { cloneDeep, debounce } from "lodash-es" import { cloneDeep, debounce } from "lodash-es"
import { computed, ref, shallowRef } from "vue" import { computed, ref, shallowRef } from "vue"
import { useRouter } from "vue-router" import { useRouter } from "vue-router"
import SearchFooter from "./SearchFooter.vue" import Footer from "./Footer.vue"
import SearchResult from "./SearchResult.vue" import Result from "./Result.vue"
/** 控制 modal 显隐 */ /** 控制 modal 显隐 */
const modelValue = defineModel<boolean>({ required: true }) const modelValue = defineModel<boolean>({ required: true })
@ -19,7 +19,7 @@ const { isMobile } = useDevice()
const inputRef = ref<HTMLInputElement | null>(null) const inputRef = ref<HTMLInputElement | null>(null)
const scrollbarRef = ref<InstanceType<typeof ElScrollbar> | null>(null) const scrollbarRef = ref<InstanceType<typeof ElScrollbar> | null>(null)
const searchResultRef = ref<InstanceType<typeof SearchResult> | null>(null) const resultRef = ref<InstanceType<typeof Result> | null>(null)
const keyword = ref<string>("") const keyword = ref<string>("")
const resultList = shallowRef<RouteRecordRaw[]>([]) const resultList = shallowRef<RouteRecordRaw[]>([])
@ -64,8 +64,8 @@ function handleClose() {
/** 根据下标位置进行滚动 */ /** 根据下标位置进行滚动 */
function scrollTo(index: number) { function scrollTo(index: number) {
if (!searchResultRef.value) return if (!resultRef.value) return
const scrollTop = searchResultRef.value.getScrollTop(index) const scrollTop = resultRef.value.getScrollTop(index)
// el-scrollbar // el-scrollbar
scrollbarRef.value?.setScrollTop(scrollTop) scrollbarRef.value?.setScrollTop(scrollTop)
} }
@ -173,17 +173,17 @@ function handleReleaseUpOrDown() {
<template v-else> <template v-else>
<p>搜索结果</p> <p>搜索结果</p>
<el-scrollbar ref="scrollbarRef" max-height="40vh" always> <el-scrollbar ref="scrollbarRef" max-height="40vh" always>
<SearchResult <Result
ref="searchResultRef" ref="resultRef"
v-model="activeRouteName" v-model="activeRouteName"
:list="resultList" :data="resultList"
:is-press-up-or-down="isPressUpOrDown" :is-press-up-or-down="isPressUpOrDown"
@click="handleEnter" @click="handleEnter"
/> />
</el-scrollbar> </el-scrollbar>
</template> </template>
<template #footer> <template #footer>
<SearchFooter :total="resultList.length" /> <Footer :total="resultList.length" />
</template> </template>
</el-dialog> </el-dialog>
</template> </template>

View File

@ -3,13 +3,14 @@ import type { RouteRecordName, RouteRecordRaw } from "vue-router"
import { getCurrentInstance, onBeforeMount, onBeforeUnmount, onMounted, ref } from "vue" import { getCurrentInstance, onBeforeMount, onBeforeUnmount, onMounted, ref } from "vue"
interface Props { interface Props {
list: RouteRecordRaw[] data: RouteRecordRaw[]
isPressUpOrDown: boolean isPressUpOrDown: boolean
} }
const props = defineProps<Props>() const props = defineProps<Props>()
/** 选中的菜单 */ /** 选中的菜单 */
const modelValue = defineModel<RouteRecordName | undefined>({ required: true }) const modelValue = defineModel<RouteRecordName | undefined>({ required: true })
const instance = getCurrentInstance() const instance = getCurrentInstance()
const scrollbarHeight = ref<number>(0) const scrollbarHeight = ref<number>(0)
@ -45,17 +46,17 @@ function getScrollTop(index: number) {
return scrollTop > scrollbarHeight.value ? scrollTop - scrollbarHeight.value : 0 return scrollTop > scrollbarHeight.value ? scrollTop - scrollbarHeight.value : 0
} }
/** 在组件挂载前添加窗口大小变化事件监听器 */ //
onBeforeMount(() => { onBeforeMount(() => {
window.addEventListener("resize", getScrollbarHeight) window.addEventListener("resize", getScrollbarHeight)
}) })
/** 在组件挂载时立即计算滚动可视区高度 */ //
onMounted(() => { onMounted(() => {
getScrollbarHeight() getScrollbarHeight()
}) })
/** 在组件卸载前移除窗口大小变化事件监听器 */ //
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener("resize", getScrollbarHeight) window.removeEventListener("resize", getScrollbarHeight)
}) })
@ -67,7 +68,7 @@ defineExpose({ getScrollTop })
<!-- 外层 div 不能删除是用来接收父组件 click 事件的 --> <!-- 外层 div 不能删除是用来接收父组件 click 事件的 -->
<div> <div>
<div <div
v-for="(item, index) in list" v-for="(item, index) in data"
:key="index" :key="index"
:ref="`resultItemRef${index}`" :ref="`resultItemRef${index}`"
class="result-item" class="result-item"

View File

@ -1,12 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from "vue" import { ref } from "vue"
import SearchModal from "./SearchModal.vue" import Modal from "./Modal.vue"
/** 控制 modal 显隐 */ /** 控制 modal 显隐 */
const modalVisible = ref<boolean>(false) const visible = ref<boolean>(false)
/** 打开 modal */ /** 打开 modal */
function handleOpen() { function handleOpen() {
modalVisible.value = true visible.value = true
} }
</script> </script>
@ -15,7 +16,7 @@ function handleOpen() {
<el-tooltip effect="dark" content="搜索菜单" placement="bottom"> <el-tooltip effect="dark" content="搜索菜单" placement="bottom">
<SvgIcon name="search" @click="handleOpen" /> <SvgIcon name="search" @click="handleOpen" />
</el-tooltip> </el-tooltip>
<SearchModal v-model="modalVisible" /> <Modal v-model="visible" />
</div> </div>
</template> </template>