如图。利用select实现搜索并且关键词高亮显示,支持滚动加载。
step1:基本页面结构
<div class="search-wrap">
<div class="search-ipt-element">
<div class="search-prepend">
<div
class="search-prepend-inner"
@click="showCityFlag=true"
>
<span>
<i class="el-icon-map-location fs20 theme-color" />
</span>
<span :class="[curCityName.length>3?'ellipsis':'' ,'city-name']">{{ curCityName }}</span>
</div>
</div>
<el-select
class="hxstyle-input-select-ele"
v-model="query.searchName"
clearable
filterable
remote
v-loadmore="loadmore"
:remote-method="remoteSearch"
@clear="clearKeyword"
placeholder="搜索小区名称/地址"
>
<el-option
v-for="item in communityList"
:key="item.value"
:label="item.name"
:value="item.code"
@click.native="handleSelect(item)"
>
<div class="search-key-item">
<div class="search-key-item-cont">
<div
class="search-key-item-title"
v-html="item.parseName"
>
</div>
<div class="search-key-item-sub">
{{ item.address }}
</div>
</div>
<div class="search-key-item-num">
{{ item.houseTypeCount }}个户型
</div>
</div>
</el-option>
<p
class="loading-txt"
v-if="loading"
>
<i class="el-icon-loading"></i>
玩命加载中...
</p>
<div
class="option-empty"
slot="empty"
>
在<span class="option-empty-tip">{{curCityName}}</span>,未搜索到与"<span class="option-empty-tip">{{query.searchName}}</span>"相关的⼩区
</div>
</el-select>
<div
slot
class="append-btn"
@click="querySearch"
>搜索</div>
</div>
</div>
step:实现远程搜索:
data() {
return {
scrollShow: false,
showCityFlag: false,
communityList: [],
loading: false,
hasLocated: false,
query: {
searchName: "",
cityCode: "",
isMatchAddr: true,
pageNo: 1,
size: 20,
},
selectParams: {
collectType: "2",
provinceId: "",
cityId: "",
areaId: "",
bedroom: -1,
livingRoom: -1,
kitchen: -1,
pageNo: 1,
size: 20,
bathroom: -1,
},
};
methods:{
//每次更新关键词。我们需要重新设置关键词并且把pageNo重置为1
remoteSearch(data) {
console.log("remoteSearch---data:", data);
this.query.searchName = data;
this.query.pageNo = 1;
this.communityList = [];
this.querySearch();
},
//点击搜索item的逻辑与本案例无关
handleSelect(){
},
//搜索关键词请求接口的逻辑
querySearch() {
getCommunityList(this.query)
.then((res) => {
this.communityList = res.data.list || [];
this.communityList = this.setHightLight(
this.communityList,
this.query.searchName
);
})
.catch((err) => {
throw new Error(err);
});
},
//设置高亮的逻辑
setHightLight(arr, keyword) {
if (arr && arr.length > 0 && keyword) {
arr = arr.filter((item) => {
let reg = new RegExp(this.query.searchName, "g");
let replaceString = `<span style="color:#ff8c00;padding:0">${keyword.trim()}</span>`;
if (item.name.match(reg)) {
//为了不影响原始name,我们这里给item重新设置一个parseName,模板中显示的是parseName
item.parseName = item.name.replace(reg, replaceString);
return item;
}
});
return arr;
}
},
//滚动加载更多逻辑
loadmore() {
this.loading = true;
this.query.pageNo++;
console.log("trigger----loadermore", this.query.pageNo);
getCommunityList(this.query)
.then((res) => {
this.loading = false;
if (this.communityList.length == res.data.total) {
return;
} else {
let list = res.data.list || [];
this.communityList = this.communityList.concat(list);
this.setHightLight(this.communityList, this.query.searchName);
}
})
.catch((err) => {});
},
}
step3:实现下拉加载:这里采用了网上其他博友的方案,通过设置一个自定义指令来实现滚动加载更多。在根目录下新建一个directive.js文件,然后在需要的页面引入
import Vue from 'vue'
let sDirective = {}
export default sDirective.install = function(vue, options) {
Vue.directive('loadmore', {
bind (el, binding) {
const selectDom = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
selectDom.addEventListener('scroll', function () {
const isEnd = this.scrollHeight - this.scrollTop <= this.clientHeight
if (isEnd) {
binding.value()
}
})
}
})
}
到此已经实现了这个效果:
有几个要注意的点:
1 关键词不要通过watch监听的方式去走请求,最好通过remote方法得到最新值以后重新赋值来处理