前言
基于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>