1.前端本地的模糊搜索原理其实很简单,我写的本地搜索只需要理解 indexOf,filter这几个就可以了,还要加上监听每次input的触发方法,vue用@input。
我先上一个效果图:
1.大概效果就是照着百度的搜索写的
.2.首先点击输入框的时候,不输入的情况下先显示推荐内容
.3.如果输入了内容则显示匹配了的搜索详情区域,如果没有匹配的内容则不显示搜索详情区域
4.搜索按钮是发送输入的内容给后台,这个按钮其实看得是前后端的配合,如果只是普通的匹配字段的那种模糊搜索,只是已经实现了,通过按钮触发的那种是复杂的模糊搜索,比如你输入“水果”,后台能帮你把苹果,雪梨等关联出来。
完整代码(包括css部分):
<template>
<div class="container">
<div class="search" :class="isShowSearch ? '' : 'search-all-bottom'">
<input :class="isShowSearch ? 'input2' : ''" v-model="inputValue
"@input="getSearch" @focus="showSearch" @blur="hideSearch" placeholder="请输入"/>
<button type="button" @click="getAccurateSearch">搜索</button>
</div>
<div class="search-box" v-show="isShowSearch">
<div v-for="item in showData" class="search-list" @mouseenter="getSearchList(item.url)"
@mouseleave="clearSearchList">
<a :href="item.url" target="_blank" @click="aHideSearch2">
<div :class="item.url == mouseKey ? 'search-title' :''">{{item.title}}</div>
</a>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
inputValue: '',
showData: [],
mouseKey: '',
isShowSearch: false, //显示搜索详情区域
isControlShow: true,
// 模拟接口获取的数据
sourceData: [{
"title": "js获取url的参数",
"url": "",
},
{
"title": "后台返回数字,前端显示对应的文字",
"url": "",
},
{
"title": "js过滤数组对象中的重复对象",
"url": "",
},
{
"title": "js统计字符串中每一个字符出现的个数",
"url": "",
},
{
"title": "vue+element-ui实现表格分页",
"url": "",
},
],
// 模拟接口获取的推荐数据
recommendedData: [{
"title": "看看我的博客",
"url": "",
},
{
"title": "去B站学习",
"url": "https://www.bilibili.com/",
},
{
"title": "去百度学习",
"url": "https://www.baidu.com/",
},
{
"title": "学习element-ui",
"url": "https://element.eleme.cn/#/zh-CN",
},
{
"title": "学习vant",
"url": "https://vant-contrib.gitee.io/vant/#/zh-CN/home",
}
]
}
},
methods: {
/**
* 模仿百度输入框的效果
* 根据输入的值进行本地的模糊搜索
* 聚焦输入框的时候,没有输入字段,先展示推荐内容
* 如果输入字段,有则显示匹配信息,没有则不显示
* */
getSearch() {
let keyWord = this.inputValue.toLowerCase()
let arr = []
// sourceData: 数据源
arr = this.sourceData.filter(item => {
if (item.title.toLowerCase().indexOf(keyWord) !== -1) {
return item
}
})
// showData:展示的数据
this.showData = arr
// 聚焦输入框的时候,没有输入字段,先展示推荐内容
this.inputValue == '' ? this.showData = this.recommendedData : ''
// 输入字段有匹配到信息,显示下拉框,没有则隐藏下拉框
this.showData.length == 0 ? this.isShowSearch = false : this.isShowSearch = true
},
// 监听输入框获取焦点
showSearch() {
if (this.inputValue == '') {
this.isShowSearch = true
this.showData = this.recommendedData
} else {
// 输入字段没有匹配到信息,隐藏下拉框
if (this.showData.length == 0) {
this.isShowSearch = false
} else {
this.isShowSearch = true
}
}
},
/**
* 输入框失去焦点的时候触发
* 判断是不是进入搜索详情区域的失去焦点
* 如果是点击搜索详情区域的,搜索详情区域不隐藏
* 点击其它区域,搜索详情区域隐藏
* */
hideSearch() {
this.showData.length == 0 ? this.isShowSearch = false : ''
this.isControlShow ? '' : this.isShowSearch = false
},
// 点击的时候隐藏搜索详情区域
aHideSearch2() {
this.isShowSearch = false
},
// 鼠标移入搜索详情区域的时候改变文字颜色
getSearchList(e) {
this.mouseKey = e
this.isControlShow = true
},
// 鼠标移出搜索详情区域的时候清空文字颜色
clearSearchList() {
this.mouseKey = ''
this.isControlShow = false
},
/**
* 发送给后台进行深层次的模糊搜索
* */
getAccurateSearch() {
// axios.post ...
}
},
created() {
this.showData = JSON.parse(JSON.stringify(this.sourceData))
}
}
</script>
<style scoped="scoped" lang="scss">
.container {
background-color: white;
width: 100%;
height: 100%;
padding: 20px;
overflow-y: auto;
.search {
display: flex;
input {
padding: 0 0 0 14px;
width: 550px;
font-size: 14px;
height: 40px;
border: 2px solid #CCC;
border-radius: 5px 0 0 5px;
}
.input2 {
border-radius: 5px 0 0 0px;
outline: none;
border: 2px solid #4662D9;
box-sizing: border-box;
border-bottom: 0;
}
input:focus {
border-radius: 5px 0 0 0px;
outline: none;
border: 2px solid #4662D9;
box-sizing: border-box;
border-bottom: 0;
}
button {
background-color: #4662D9;
color: white;
width: 80px;
border: 2px solid #4662D9;
cursor: pointer;
}
}
.search-all-bottom {
input:focus {
border: 2px solid #4662D9;
}
}
.search-box {
width: 550px;
padding: 5px 0 10px 14px;
border: 2px solid #4662D9;
border-top: 0;
.search-list {
width: 550px;
margin-top: 5px;
.search-title {
color: blue;
}
}
}
}
</style>
详解一下,做个简单的模糊搜索,不考虑css部分,模糊搜索 代码就几行 @input=“getSearch”,一直触发下面的方法就可以了,使用toLowerCase()转小写是为了本地搜索更加彻底。indexOf是判断字符串是否包含当前字段,没有是返回-1,filter把存在的数组对象筛选出来。
getSearch() {
let keyWord = this.inputValue.toLowerCase()
let arr = []
// sourceData: 数据源
arr = this.sourceData.filter(item => {
if (item.title.toLowerCase().indexOf(keyWord) !== -1) {
return item
}
})
// showData:展示的数据
this.showData = arr
},
剩余的代码基本就是因为要写样式才加上去的,为了模仿百度搜索框,累了啊,思路清晰写功能代码一下子就写完了,样式需要慢慢调试