不知道如何 主动触发 fetch-suggestions 方法? 那往下看就对了!
vue3, 在使用 element-plus 的远程搜索,筛选结果的组件 el-autocomplete 时候,因为要用到搜索范围,所以使用了 前置的插槽 放置下拉选择组件 el-select。
使用 autocomplete 组件
范围有:标题、内容、所有。当每次切换范围的时候,需要重新请求后台并将结果,并重新显示出来,即重新触发一下组件的 fetch-suggestions绑定的方法。
但是这个方法的参数有个cb回调函数,js无法直接调用 fetch,
fetch-suggestions
那我们就看看这个 fetch 到底 做了些什么。查看源码:
autocomplete2.js
根据以上源码可知,fetch-suggestions 调用方法是为了将想要回显的数据,传递到 fetch 的第二个参数回调函数里,然后 suggestions.value = suggestionsArg;
也就是说fetch 方法的目的是赋值 suggestions ,就是你实际需要设置的回显的数据。再看它导出的属性里有这个属性。
那么问题应该就解决了,通过 ref 获取这个组件实例然后设置 suggestions 值。值得注意的是这里的 focus 方法,需要在设置 suggestions 之前调用,否则 无法正常回显数据。
组件的 expose
总结: 如何主动触发 el-autocomplete组件的 fetch-suggestions 方法,达到刷新筛选结果效果?
不需要触发方法, 1、获取 ref 组件实例,2、设置focus,3、设置 suggestions。
最终代码如下,需要的朋友可以参考下:
<template>
<el-autocomplete
class="inputSearch"
v-model="searchInput"
size="default"
ref="myAutocomplete"
:fetch-suggestions="searchChange"
:trigger-on-focus="true"
placeholder="Search article"
@select="handleSelect"
@keyup.enter="submitSearch"
maxlength="30"
clearable
>
<template #prepend>
<el-select size="default" v-model="searchOption" style="width: 7rem">
<el-option class="my-select" v-for="item in searchOptionList" :label="item.name" :value="item.value" />
</el-select>
</template>
<template #append>
<el-button :icon="Search" @click="submitSearch" />
</template>
<template #default="{ item }">
<div class="overHiden2 search_item">
<span class="search_item_title" :title="item.value" v-html="filterTitle(item.value)"></span>
<el-button class="search_item_delete" type="text" title="查看">{{ item.created }}</el-button>
</div>
</template>
</el-autocomplete>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
// 搜索内容
let searchInput = ref("");
// 绑定el-autocomplete组件
const myAutocomplete = ref(null);
// 搜索选择范围
let searchOption = ref("title");
let searchOptionList = ref([
{ name: '标题', value: 'title' },
{ name: '内容', value: 'content' },
{ name: '全部', value: 'all' },
]);
// links 这里是声明,从后台获取的数据赋值给它
const links = ref<LinkItem[]>([]);
// fetch-suggestions
const searchChange = (str: string, cb: (arg: any) => void) => {
if (!searchInput.value.trim()) { // 如果为空,则直接返回空
cb([]);
return
}
// 这里执行 自定义过滤
let results = str ? links.value.filter(createFilter(str)) : links.value; // createFilter自己写规则
cb(results);
}
// 监听搜索‘范围’数据变化,并重新回显筛选结果 【重点看这里!!!】
watch(() => searchOption.value, () => {
// 重置原始数据
links.value = [];
// 如果为空,则不操作
let str = searchInput.value.trim();
if (!str) {
return;
}
// 后台获取数据 赋值给 links.value
searchPostList();
// 获取此组件实例
let complete = (myAutocomplete.value as any);
// 同样的自定义过滤
let results = str ? links.value.filter(createFilter(str)) : links.value;
// 实例重新聚焦,
complete.focus();
// 筛选结果 赋值 suggestions,达到触发页面筛选数据变化的目的
complete.suggestions = results;
})
// 给每个结果中匹配字符高亮,v-html="filterTitle(item.value)" 后续篇章里详细讲解一下
const filterTitle = (originStr: string) => {
if (!searchInput.value) {
return originStr;
}
// 将匹配的字符添加一个‘高亮’的标签外表
let str = searchInput.value;
const regEscape = (v: any) => v.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
return originStr.replace(new RegExp(regEscape(str), "ig"), '<span style="color: #2cc0da">$&</span>');
}
</script>
<style lang="scss" scoped>
// 略
</style>
另外,在vue2中我看到有博主已经给出了方案,可以参考yujiuchun的文章:element ui远程搜索主动触发fetch-suggestions - 简书https://www.jianshu.com/p/3f0c813d28ac 。
以上。