1:效果图如下
不多说上代码
2:引入方式 (fuse更多使用功能可以百度搜索)
方式一:cdn方式引入 fuse.js 轻量级模糊搜索,在html页面里面引入,引入后记得重启,不然不生效
https://cdn.bootcdn.net/ajax/libs/fuse.js/7.0.0/fuse.basic.min.js
方式二:也可以不用cdn方式,npm install fuse.js,需要在子组件里面加上这个 import Fuse from 'fuse.js'
3:可以把这个封装成一个组件使用
父:
<headerSearch id="header-search" class="right-menu-item" />
import headerSearch from "./headerSearch";
components:{headerSearch}
子:就是下面代码 (cdn方式)
<template>
<div :class="{'show':show}" class="header-search">
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
<el-select
ref="headerSearchSelect"
v-model="search"
:remote-method="querySearch"
filterable
default-first-option
remote
placeholder="请输入要搜索的左侧目录"
class="header-search-select"
@change="change"
>
<el-option v-for="item,index in options" :key="index" :value="item.item.urlLabel" :label="item.item.name.join(' > ')" />
</el-select>
</div>
</template>
<script>
// fuse is a lightweight fuzzy-search module
// make search results more in line with expectations
//import Fuse from 'fuse.js'
import path from 'path'
export default {
name: 'HeaderSearch',
data() {
return {
search: '',
options: [],
searchPool: [],
show: false,
fuse: undefined
}
},
computed: {
routes() {
return this.$store.getters.navList
}
},
watch: {
routes() {
this.searchPool = this.generateRoutes(this.routes)
},
searchPool(list) {
this.initFuse(list)
},
show(value) {
if (value) {
document.body.addEventListener('click', this.close)
} else {
document.body.removeEventListener('click', this.close)
}
}
},
mounted() {
this.searchPool = this.generateRoutes(this.routes)
},
methods: {
click() {
this.show = !this.show
if (this.show) {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
}
},
close() {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
this.options = []
this.show = false
},
change(val) {
this.$router.push(val)
this.search = ''
this.options = []
this.$nextTick(() => {
this.show = false
})
},
initFuse(list) {
this.fuse = new Fuse(list, {
shouldSort: true,
threshold: 0.4,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [{
name: 'name',
weight: 0.7
}, {
name: 'urlLabel',
weight: 0.3
}]
})
},
// Filter out the routes that can be displayed in the sidebar
// And generate the internationalized title
generateRoutes(routes, basePath = '/', prefixTitle = []) {
let res = []
for (const router of routes) {
// skip hidden router
if (router.hidden) { continue }
// console.log(router)
const data = {
urlLabel: path.resolve(basePath, router.urlLabel),
name: [...prefixTitle]
}
if (router && router.name) {
data.name = [...data.name, router.name]
// if (router.redirect !== 'noRedirect') {
// only push the routes with title
// special case: need to exclude parent router without redirect
res.push(data)
// }
}
// recursive child routes
if (router.children) {
const tempRoutes = this.generateRoutes(router.children, data.urlLabel, data.name)
if (tempRoutes.length >= 1) {
res = [...res, ...tempRoutes]
}
}
}
return res
},
querySearch(query) {
if (query !== '') {
this.options = this.fuse.search(query)
} else {
this.options = []
}
// console.log(this.options)
}
}
}
</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>
5:数据结构
routes() {
return this.$store.getters.navList
}
navList对应的数据结构是这样的
有其他问题可以评论联系,*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。