前言
基于Vue2.5+ElementPlus实现的一个自定义带历史记录的搜索框组件
效果如图:
基本样式:
获取焦点后:
这里的历史记录默认最大存储10条,同时右侧的清空按钮可以清空所有历史记录。
同时搜索记录也支持点击搜索,按下enter也可以直接搜索
vue代码
为什么叫vue2.5是因为我在vue3的框架下同时写vue2和vue3的语言。
这里要提前在main.js中提前注册element-plus中的图标,或者按需引入也可以。
这里我通过将历史记录直接存入到一个列表,然后存储在本地存储,每次有新的搜索记录时,unshift列表头部元素,这样每次在最上方展示的历史记录就是最新的,同时也方便删除旧的历史记录时直接pop掉即可。
实现起来比较简单,可以根据不同需求应用不同场景。
<template><!-- 搜索框 --><div class="search-area" ref="searchbar"><el-input v-model="searchcontent" style="max-width: 500px;width: 500px;" :placeholder="placeholder"class="input-with-select" maxlength="56" size="large" @focus="isshow = true" @keydown.enter="searchblog"><template #append><el-button style="background-color: #fc5531;" size="large" @click="searchblog" :disabled="isclick"><span style="color: white;font-weight: 500;display: flex;"><el-icon style="margin-right: 10px;"><Search></Search></el-icon>搜索</span></el-button></template></el-input><div class="search-drop-menu" v-show="isshow"><div class="search-history" v-show="searchhistorylist.length > 0"><div class="search-title">搜索历史<span class="search-clear" @click="clearhistory"><el-icon><Delete></Delete></el-icon><span>清空</span></span></div><div><div v-for="(item, index) in searchhistorylist" :key="index" class="history-item"><div @click="searchhistory(item)">{{ item }}</div></div></div></div><div class="search-hot"><!-- 留着做推荐 --><div class="search-title">搜索发现</div></div></div></div>
</template><script>import { ElMessage } from 'element-plus';export default {name: 'SearchInput',data() {return {searchcontent: '',//搜索内容placeholder: '请输入',//以后有了推荐系统可以预置用户想搜索的内容isshow: false,searchhistorylist: [], //搜索历史列表}},methods: {//搜索博客内容searchblog() {//先判断输入是否为空if (this.searchcontent == '') {ElMessage({ type: 'info', message: '输入不能为空', duration: 1500 });return;}//隐藏搜索框this.isshow = false;//加入到搜索历史列表this.searchhistorylist.unshift(this.searchcontent);//判断列表长度是否大于10 如果大于了就删除一个最旧的while (this.searchhistorylist.length > 10) {this.searchhistorylist.pop();}//保存到本地存储localStorage.setItem("search_history_list", JSON.stringify(this.searchhistorylist));//跳转搜索内容页面location.href = '/blog/search?q=' + this.searchcontent;},//搜索历史内容searchhistory(val) {//隐藏搜索框this.isshow = false;//加入到搜索历史列表this.searchhistorylist.unshift(val);//判断列表长度是否大于10 如果大于了就删除一个最旧的while (this.searchhistorylist.length > 10) {this.searchhistorylist.pop();}//保存到本地存储localStorage.setItem("search_history_list", JSON.stringify(this.searchhistorylist));//跳转搜索内容页面location.href = '/blog/search?q=' + val;},//清除历史记录clearhistory() {this.searchhistorylist = [];localStorage.removeItem('search_history_list');ElMessage({ type: 'success', message: '历史记录清除成功', duration: 1500 });}},mounted() {//获取用户搜索历史let list = JSON.parse(localStorage.getItem("search_history_list")) || null;if (list == null) {console.log("无本地搜索历史");return;}this.searchhistorylist = list;//设置一个监听 点击搜索框其他区域就隐藏document.addEventListener("click",(e) => {if (e.target.className=='el-main') {this.isshow = false;}},true);}}
</script><style scoped>
.search-drop-menu {position: absolute;width: 100%;-webkit-box-sizing: border-box;box-sizing: border-box;padding: 8px 0 12px;font-size: 14px;font-weight: 400;-webkit-box-shadow: 0 0 10px 2px rgb(0 0 0 / 6%);box-shadow: 0 0 10px 2px rgb(0 0 0 / 6%);border-radius: 0 0 4px 4px;background: #fff;color: #555666;top: 39px;left: 0;min-height: 200px;height: auto;text-align: left;z-index: 9999; /* 设置一个很高的值确保在最上层 */}.search-history {width: 50%;float: left;
}.search-hot {width: 50%;float: left;
}.search-title {padding-left: 16px;height: 32px;font-size: 12px;color: #fc5531;line-height: 32px;position: relative;
}.history-item {overflow: hidden;white-space: nowrap;text-overflow: ellipsis;position: relative;display: block;width: 100%;padding: 0 16px 0 16px;-webkit-box-sizing: border-box;box-sizing: border-box;height: 32px;line-height: 32px;cursor: pointer;display: -webkit-box;display: -ms-flexbox;display: flex;-webkit-box-pack: justify;-ms-flex-pack: justify;justify-content: space-between;-webkit-box-align: center;-ms-flex-align: center;align-items: center;
}.search-clear {right: 0px;color: #ccccd8;position: absolute;height: 100%;right: 16px;top: 0;cursor: pointer;
}
</style>