效果图:
一、组件封装:
HTML:
<template>
<div class="suggestion-field-box">
<div class="sug-input">
<input
class="uni-input"
v-model="myValue"
@input="onKeyInput"
:placeholder="placehText"
:disabled="inputDisabled"
@blur="blurHandler"
/>
</div>
<div class="suggestion-field" v-if="isSuggestionVisible">
<ul class="suggesstion-list">
<li
v-for="(item, index) in suggestionData"
:key="index"
@click="suggestionItemClickHandler(item)"
>
<template v-if="$slots.default">
<slot :row="item"></slot>
</template>
<template v-else>
{{ item.label }}
</template>
</li>
</ul>
</div>
</div>
</template>
JS:
<script>
import { debounce } from "lodash"; //防抖动
let debounceTime = 400;
export default {
props: {
fetchSuggestions: { //可通过外部传入后缀填充函数
type: Function,
default: null
},
inputDisabled: {
type: Boolean,
default: false,
},
suggestionValue: { //外部传入的输入框初始化值
type: String,
default: "",
},
placehText: {
type: String,
default: "",
},
debounce: {
type: Number,
default: debounceTime,
},
},
watch: {
suggestionValue(val){
this.myValue = val;
}
},
data() {
return {
myValue: this.suggestionValue,
suggestionData: [],
isSuggestionVisible: false,
};
},
methods: {
onKeyInput: debounce(function (event) {
this.fetchSuggestionsHandler(event.target.value);
}, debounceTime),
async fetchSuggestionsHandler(newValue) {
if (!this.fetchSuggestions) {
return;
}
if (!newValue.trim()) {
this.isSuggestionVisible = false;
return;
}
const res = await this.fetchSuggestions(newValue);
this.suggestionData = res;
this.isSuggestionVisible = res && res.length > 0;
},
blurHandler() {
setTimeout(() => {
this.isSuggestionVisible = false;
}, 100);
},
suggestionItemClickHandler(item) {
this.myValue = item.label;
this.$emit("setValue", item.label);
this.isSuggestionVisible = false;
},
},
created() {
debounceTime = this.debounce;
},
};
</script>
CSS:
<style lang="less" scoped>
.suggestion-field-box {
position: relative;
}
.suggestion-field {
position: absolute;
left: 0;
right: 0;
top: 100%;
z-index: 1;
background: #fff;
}
ul {
list-style: none;
padding-inline-start: 0px;
}
.suggesstion-list {
border-radius: 8px;
box-shadow: 0 0 5px #999;
padding: 10px 0 10px 10px;
li {
padding-bottom: 10px;
text-align: left;
+ li {
padding-top: 10px;
border-top: 1px solid #f5f5f5;
}
}
}
</style>
二、使用示例:
HTML:
<div class="msg-box">
<div class="input-text"><span>邮箱:</span></div>
<suggestion-input
:suggestionValue="email"
:placehText="inputDisabled ? '' : '请输入邮箱'"
:inputDisabled="inputDisabled"
@setValue="changeEmail"
:fetchSuggestions="fetchEmailSuggestions"
class="input-box"
>
</suggestion-input>
</div>
JS:
fetchEmailSuggestions(email) {
//在此编写自己的填充逻辑即可
if (email.indexOf("@") != -1) {
return [];
}
return ["@qq.com", "@163.com", "@gmail.com", "yahoo.com"].map(
(item) => {
return {
label: email + item,
};
}
);
},