序文
el-autocomplete は、 elementでよく使用されるコンポーネントであり、入力ボックスの自動補完機能を実現するために使用されます。ただし、デフォルト設定ではリモート検索に問題があり、範囲一致を実行できません。つまり、入力されたキーワードが選択肢の部分文字列やキーワードの部分文字列であっても、選択肢を正しく検索することができません。この記事では、この問題を解決し、よりスマートなel-autocompleteリモート検索機能を実装する方法について説明します。
前の未調整の例
値の範囲を検索する場合、値の範囲を直接検索することはできないことがわかりますが、その範囲も検索できることをどのように認識すればよいでしょうか? 実際、鍵はメソッドにありますcreateStateFilter
。
デフォルトの
createStateFilter
メソッド
createStateFilter(queryString) {
return (state) => {
return (
state.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
);
};
},
間隔も検索できることを実現するには、createStateFilter
メソッドを変更する必要があります。現在の実装では、入力文字列をサイト名のプレフィックスと照合するため、名前の先頭のみが検索されます。次に、createStateFilter
メソッドのロジックを変更します。
解決策 1:
このメソッドは、入力文字列とサイト名の単純な包含一致を実行します。入力文字列がサイト名の部分文字列である限り、検索を実行できます。この方法の利点は、シンプルかつ直接的であり、実装が比較的簡単で、一部の小規模な検索要件には十分である可能性があることです。
欠点:
一致精度が低い: 入力文字列がサイト名の部分文字列である限り、検索は実行できますが、より正確な間隔の一致は達成できません。
複数のキーワードの検索サポートは完全ではありません。入力文字列に複数のキーワードが含まれている場合、このメソッドは各キーワードを検索するロジックを実現できません。
createStateFilter(queryString) {
return (state) => {
return (
state.value.toLowerCase().indexOf(queryString.toLowerCase()) !== -1
);
};
},
解決策 2:
このアプローチにより、よりスマートな検索機能が提供されます。キーワードとサイト名の間隔一致を実現し、複数のキーワード検索をサポートします。
アドバンテージ:
より正確な一致: キーワードの間隔一致を実現でき、キーワードがサイト名の先頭でなくても検索できます。
複数キーワード検索のサポート: 入力文字列に複数のキーワードが含まれる場合を処理し、各キーワードが確実に一致するようにします。
createStateFilter(queryString) {
return (state) => {
const stationName = state.value.toLowerCase();
queryString = queryString.toLowerCase();
if (stationName.indexOf(queryString) !== -1) {
// 如果输入的字符串是站点名称的子串,则可以进行搜索
return true;
}
const stationNameArr = stationName.split(" ");
const queryStringArr = queryString.split(" ");
for (let i = 0; i < stationNameArr.length; i++) {
if (
queryStringArr.every(
(query) => stationNameArr[i].indexOf(query) !== -1
)
) {
// 如果输入的字符串的每个关键词都在站点名称中找到了对应的子串,则可以进行搜索
return true;
}
}
return false;
};
},
まとめると、どちらの方法でもこの要件を満たすことができますが、単純な検索機能のみが必要で、高い検索精度を必要としない場合は、最初の方法で十分にシンプルで効果的です。ただし、範囲一致機能と複数キーワード検索のサポートを備えた、よりスマートな検索を実装する必要がある場合は、2 番目の方法の方が適しています。特定のニーズに応じて、使用する方法を選択できます。
完全なコード
<template>
<div>
<el-autocomplete v-model="state" clearable :fetch-suggestions="querySearchAsync" placeholder="请输入内容" @select="handleSelect">
</el-autocomplete>
</div>
</template>
<script>
export default {
data() {
return {
restaurants: [
{
value: "北京省市辖区东城区", address: "1" },
{
value: "河南省郑州市二七区", address: "2" },
{
value: "辽宁省沈阳市大东区", address: "3" },
{
value: "四川省成都市锦江区", address: "4" },
{
value: "海南省三亚市天涯区", address: "5" },
{
value: "浙江省杭州市余杭区", address: "6" },
],
state: "",
timeout: null,
};
},
methods: {
querySearchAsync(queryString, cb) {
var restaurants = this.restaurants;
var results = queryString
? restaurants.filter(this.createStateFilter(queryString))
: restaurants;
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
cb(results);
}, 500 * Math.random());
},
createStateFilter(queryString) {
return (state) => {
const stationName = state.value.toLowerCase();
queryString = queryString.toLowerCase();
if (stationName.indexOf(queryString) !== -1) {
// 如果输入的字符串是站点名称的子串,则可以进行搜索
return true;
}
const stationNameArr = stationName.split(" ");
const queryStringArr = queryString.split(" ");
for (let i = 0; i < stationNameArr.length; i++) {
if (
queryStringArr.every(
(query) => stationNameArr[i].indexOf(query) !== -1
)
) {
// 如果输入的字符串的每个关键词都在站点名称中找到了对应的子串,则可以进行搜索
return true;
}
}
return false;
};
},
handleSelect(item) {
console.log(item, "选择数据");
},
},
};
</script>