refactor: 重构 SearchMenu 组件结构
This commit is contained in:
parent
b18bf9d4b5
commit
ff4ae8ba5b
@ -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>
|
@ -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"
|
@ -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>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user