实现el-select的远程搜索,并且展示最近搜索的十条数据
目录
实现el-select的远程搜索,并且展示最近搜索的十条数据
项目场景:
使用el-select实现远程搜索,并且可以输入进行搜索,首次点击的时候显示十条历史记录,在输入之后就展示远程搜索返回的数据
问题描述
1、el-select的远程搜索如果实现
2、怎么记录历史搜索的数据
3、如果实现输入之后点击回车就进入到结果页面
问题分析:
远程搜索的实现
远程搜索的实现,el-select组件中有远程搜索的API
<el-select popper-class="social-economy-search-input" v-model="keywords" placeholder="请输入关键词" filterable remote :remote-method="remoteMethod" :loading="loadingOption" @click="getHistorySearch" @change="handleChange" @keyup.enter="keyupEnter" >
remote:其中的选项是否从服务器远程加载
remote-method:自定义远程搜索方法
loading:是否正在从远程获取数据
利用remote-method这个API自定义远程搜索的方法,当进行远程搜索的时候就开启loading,有数据结束之后就关闭loading
这里我为什么要定义这三个方法呢?
@click=“getHistorySearch” ,点击select选择器的时候,获取历史记录
@change=“handleChange”,当select选择器的数据发生变化的时候触发
@keyup.enter=“keyupEnter”,当回车的时候触发
//远程搜索
const remoteMethod = async (val) => {
if (val) {
loadingOption.value = true;
keywords.value = val;
let params = {
keywords: keywords.value,
pageSize: pageSize.value,
};
let res = await httpPost(
"economicStatistics/v1/searchIndicatorListByKeywords",
params
);
if (res.code == 0) {
options.value.label = "";
options.value.list = res.data;
loadingOption.value = false;
} else {
loadingOption.value = false;
}
} else {
keywords.value = "";
loadingOption.value = false;
}
};
历史记录的实现
要实现历史记录就要记录用户输入后请求的每一次数据,将用户的输入存储localStorage中,在用户点击select的时候,展示最近十条历史记录
注意:获取最近十条历史记录,当用户有输入与之前记录相同的关键字,就删除掉之前的记录只展示最新的相同的记录
//历史记录列表
const historySearchKeyWordsList = ref([]);
//删除历史搜索中与当前输入相同的关键字
const removeDuplicate = () => {
historySearchKeyWordsList.value =
JSON.parse(localStorage.getItem("keywords")) || [];
const index = historySearchKeyWordsList.value.indexOf(keywords.value); // 查找新元素在数组中的索引
if (index !== -1) {
historySearchKeyWordsList.value.splice(index, 1); // 删除数组中与新元素相同的旧元素
}
return historySearchKeyWordsList.value;
};
//存储历史搜索关键字
const saveKeyWords = () => {
if (historySearchKeyWordsList.value.length >= 10) {
historySearchKeyWordsList.value.pop(); // 删除最早存储的关键字
}
historySearchKeyWordsList.value.unshift(keywords.value);
localStorage.setItem(
"keywords",
JSON.stringify(historySearchKeyWordsList.value)
);
};
//获取历史搜索
const getHistorySearch = () => {
const keywords = JSON.parse(localStorage.getItem("keywords")) || [];
options.value.label = "历史搜索";
options.value.list = keywords.map((item) => {
return { name: item };
});
};
解决方案:
<template>
<div class="database-index">
<div class="social-economy">
<div class="social-economy-logo">
<img
src="@/assets/imgs/database/social-economy/socialEconomy-logo.png"
alt=""
/>
</div>
<div class="social-economy-search">
<el-select
popper-class="social-economy-search-input"
v-model="keywords"
placeholder="请输入关键词"
filterable
remote
:remote-method="remoteMethod"
:loading="loadingOption"
@click="getHistorySearch"
@change="handleChange"
@keyup.enter="keyupEnter"
>
<template #prefix>
<el-icon class="el-input__icon"><search /></el-icon>
</template>
<el-option-group :key="options.label" :label="options.label">
<el-option
v-for="item in options.list"
:key="item.name"
:label="item.name"
:value="item.name"
>
<div
class="option-list"
@click="getCurrentId(item.indicatorUniqueId)"
>
<el-icon class="el-input__icon">
<search />
</el-icon>
<span
style="padding-left: 8px"
v-html="highlightKeywords(item.name, keywords)"
></span>
</div>
</el-option>
</el-option-group>
</el-select>
</div>
<div class="social-economy-list"></div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { httpPost } from "@/api/httpService.js";
import { useRoute, useRouter } from "vue-router";
import { highlightKeywords } from "@/utils/highlightKeywords.js";
import { Debounce } from "@/utils/utils";
import { ElMessage } from "element-plus";
const route = useRoute();
const router = useRouter();
const loadingOption = ref(false); //是否正在加载选项数据
const options = ref({ label: "", list: [] });
const keywords = ref("");
const pageNum = ref(1);
const pageSize = ref(10);
const currentId = ref("");
//获取远程搜索点击时当前指标id
const getCurrentId = (id) => {
currentId.value = id;
};
//远程搜索
const remoteMethod = async (val) => {
if (val) {
loadingOption.value = true;
keywords.value = val;
let params = {
keywords: keywords.value,
pageSize: pageSize.value,
};
let res = await httpPost(
"economicStatistics/v1/searchIndicatorListByKeywords",
params
);
if (res.code == 0) {
options.value.label = "";
options.value.list = res.data;
loadingOption.value = false;
} else {
loadingOption.value = false;
}
} else {
keywords.value = "";
loadingOption.value = false;
}
};
//前往搜索结果页
const goSearchResult = () => {
if (keywords.value && keywords.value !== "") {
router.push({
path: "/database/social-economy/search-result",
query: {
keywords: keywords.value,
},
});
removeDuplicate();
saveKeyWords();
} else {
ElMessage.warning("请输入搜索关键字!");
}
};
const handleChange = async (value) => {
keywords.value = value != null && value != "" ? value : "";
if (options.value.label) {
goSearchResult();
} else {
await saveSearchKeyWords();
router.push({
path: "/database/social-economy/indicator-result",
query: {
type: 3,
id: currentId.value,
},
});
}
};
const keyupEnter = () => {
goSearchResult();
};
//历史记录列表
const historySearchKeyWordsList = ref([]);
//删除历史搜索中与当前输入相同的关键字
const removeDuplicate = () => {
historySearchKeyWordsList.value =
JSON.parse(localStorage.getItem("keywords")) || [];
const index = historySearchKeyWordsList.value.indexOf(keywords.value); // 查找新元素在数组中的索引
if (index !== -1) {
historySearchKeyWordsList.value.splice(index, 1); // 删除数组中与新元素相同的旧元素
}
return historySearchKeyWordsList.value;
};
//存储历史搜索关键字
const saveKeyWords = () => {
if (historySearchKeyWordsList.value.length >= 10) {
historySearchKeyWordsList.value.pop(); // 删除最早存储的关键字
}
historySearchKeyWordsList.value.unshift(keywords.value);
localStorage.setItem(
"keywords",
JSON.stringify(historySearchKeyWordsList.value)
);
};
//获取历史搜索
const getHistorySearch = () => {
const keywords = JSON.parse(localStorage.getItem("keywords")) || [];
options.value.label = "历史搜索";
options.value.list = keywords.map((item) => {
return { name: item };
});
};
//保存远程搜索关键字
const saveSearchKeyWords = async () => {
let params = {
keywords: keywords.value,
};
httpPost("economicStatistics/v1/saveSearchKeywords", params);
};
</script>