headerSearch组件:在指定搜索框中对当前应用中所有页面进行检索,以select形式展示出被检索的页面,以达到快速进入的目的;
一、原理:
1、根据指定内容对所有页面进行检索;
2、以select形式展示检索出的页面;
3、通过检索页面可快速进入对应页面。
二、方案:
1、创建 headerSearch 组件,用作样式展示和用户输入内容获取
2、获取所有的页面数据,用作被检索的数据源
3、根据用户输入内容在数据源中进行模糊搜索
4、把搜索到的内容以 select 进行展示
5、监听 select 的 change 事件,完成对应跳转
三、代码:
点击展示js代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <template> <div :class="{ show: isShow }" class="header-search"> <svg-icon id="guide-search" class-name="search-icon" icon="search" @click.stop="onShowClick" /> <el-select ref="headerSearchSelectRef" class="header-search-select" v-model="search" filterable default-first-option remote placeholder="Search" :remote-method="querySearch" @change="onSelectChange" > <el-option v-for="option in searchOptions" :key="option.item.path" :label="option.item.title.join(' > ')" :value="option.item" ></el-option> </el-select> </div> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| <script setup> import { computed, ref, watch } from 'vue' import { generateRoutes } from './FuseData' import Fuse from 'fuse.js' import { filterRouters } from '@/utils/route' import { useRouter } from 'vue-router' import { watchSwitchLang } from '@/utils/i18n'
const isShow = ref(false)
const headerSearchSelectRef = ref(null) const onShowClick = () => { isShow.value = !isShow.value headerSearchSelectRef.value.focus() }
const search = ref('')
const searchOptions = ref([])
const querySearch = query => { if (query !== '') { searchOptions.value = fuse.search(query) } else { searchOptions.value = [] } }
const onSelectChange = val => { router.push(val.path) onClose() }
const router = useRouter() let searchPool = computed(() => { const filterRoutes = filterRouters(router.getRoutes()) return generateRoutes(filterRoutes) })
let fuse const initFuse = searchPool => { fuse = new Fuse(searchPool, { shouldSort: true, threshold: 0.4, minMatchCharLength: 1, keys: [ { name: 'title', weight: 0.7 }, { name: 'path', weight: 0.3 } ] }) } initFuse(searchPool.value)
const onClose = () => { headerSearchSelectRef.value.blur() isShow.value = false searchOptions.value = [] }
watch(isShow, val => { if (val) { document.body.addEventListener('click', onClose) } else { document.body.removeEventListener('click', onClose) } })
watchSwitchLang(() => { searchPool = computed(() => { const filterRoutes = filterRouters(router.getRoutes()) return generateRoutes(filterRoutes) }) initFuse(searchPool.value) }) </script>
<style lang="scss" scoped> .header-search { font-size: 0 !important; .search-icon { cursor: pointer; font-size: 18px; vertical-align: middle; } .header-search-select { font-size: 18px; transition: width 0.2s; width: 0; overflow: hidden; background: transparent; border-radius: 0; display: inline-block; vertical-align: middle;
::v-deep .el-input__inner { border-radius: 0; border: 0; padding-left: 0; padding-right: 0; box-shadow: none !important; border-bottom: 1px solid #d9d9d9; vertical-align: middle; } } &.show { .header-search-select { width: 210px; margin-left: 10px; } } } </style>
|
四、数据源:
FuseData.js
点击展示js代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import path from 'path' import i18n from '@/i18n'
export const generateRoutes = (routes, basePath = '/', prefixTitle = []) => { let res = [] for (const route of routes) { const data = { path: path.resolve(basePath, route.path), title: [...prefixTitle] } const re = /.*\/:.*/ if ( route.meta && route.meta.title && !re.exec(route.path) && !res.find(item => item.path === data.path) ) { const i18ntitle = i18n.global.t(`msg.route.${route.meta.title}`) data.title = [...data.title, i18ntitle] res.push(data) }
if (route.children) { const tempRoutes = generateRoutes(route.children, data.path, data.title) if (tempRoutes.length >= 1) { res = [...res, ...tempRoutes] } } } return res }
|