目录

elementUI中el-autocomplete和el-select用法和各种坑

目录

elementUI中el-autocomplete和el-select用法和各种坑

最近在vue2+elementUI的项目中遇到了很多坑,这里记录一下,并附上我避坑的解决方案,希望对大家今后的开发有所帮助。

需求:要在文本框中通过输入关键字模糊搜索出一个列表,在列表中选中一个值后,这个选中的对象的其他属性要赋值到提交对象上,用于提交。

我最开始考虑到用el-autocomplete远程搜索自动补全组件,用法是这样的:

<el-autocomplete
	v-model="aduitObj.tmpCompanyName"
	:fetch-suggestions="queryCompanyAsync"
	placeholder="模糊搜索公司名称"
	@select="handleSelectCompany"
	:trigger-on-focus="false"
	:debounce=0
	clearable
>
	<i slot="suffix" class="el-input__icon el-icon-search"></i>
</el-autocomplete>

async queryCompanyAsync(queryString, cb){//模糊搜索公司名称
console.info("query------",queryString, "tmpCompanyName====",this.aduitObj.tmpCompanyName);
if(!this.aduitObj.applyType){
this.$alert('请先选择公司类型!', '警告', { confirmButtonText: '确定' });
return;
}else if(!queryString || queryString.length==0 || queryString.trim().length==0){
cb([]);
return;
}
let param = {
name: queryString,
type: this.aduitObj.applyType
};
let {data: res} = await queryCompanysByName(JSON.stringify(param));
if(res && res.success){
var resArr = res.result.map(function(rItem){
rItem.value = rItem.company;
return rItem;
});
cb(resArr);
}
},
handleSelectCompany(val){//选择某个公司
console.info("select company=======",val);
this.aduitObj.tmpCompanyName = val.company;
this.aduitObj.authCompanyId = val.id;//回显和判断那里用的是这个 id
//buthCompanyName/buthCompanyId/buthCompanyXId 都是提交接口需要的参数
this.aduitObj.buthCompanyName = val.company;
this.aduitObj.buthCompanyId = val.id;
this.aduitObj.buthCompanyXId = val.xId;
},

这里有个坑,fetch-suggestions 接收函数需要执行 cb()回调函数并把数组返回到 cb 的回调参数中。还有一点,需要格外注意,数组中每个值必须得有 value 字段,最终选中的 value 值会自动赋值给 v-model 的值。

继续完善,需要给 el-autocomplete 加个必填项校验,需要这样做:

(这里一并讲一下 elemenutui 双属性的校验写法 el-form-item 的 props 写 2 个属性,逗号分隔开,校验规则跟这 2 个属性名对应即可。)

<el-form :model="aduitObj" :rules="aduitRules" ref="aduitRules" label-width="150px">
<el-form-item label="认证公司选择:" prop="applyType,tmpCompanyName" v-show="aduitObj.status==1" style="margin-bottom: 22px;">
<el-row :gutter="0">
<el-col :span="4">
<el-form-item prop='applyType'>
<el-select v-model="aduitObj.applyType" placeholder="请选择" @change="changeApplyType">
<el-option label="客户" value="1"></el-option>
<el-option label="经销商" value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="20">
<el-form-item prop='tmpCompanyName'>
<el-autocomplete
...... ......
</el-autocomplete>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
。。。。。。
</el-form>

export default {
components: { },
data(){
var checkApplyType = (rule, value, callback) => {
if (this.aduitObj.status==1 && !value) {
return callback(new Error('请选择认证公司类型!'));
}
return callback();
};
var checkCompanyId = (rule, value, callback) => {
console.info("checkCompanyId-------", value, this.aduitObj.status,this.aduitObj.authenticationCompanyId)
if (this.aduitObj.status==1 && (!value || !this.aduitObj.authCompanyId)) {//编辑回显值的时候用的是 authCompanyId 值
return callback(new Error('请选择认证公司!'));
}
return callback();
};
return {
aduitObj:{},
... ...
aduitRules:{
...... ......
applyType:[{ validator: checkApplyType, trigger: 'change' }],
tmpCompanyName:[{ validator: checkCompanyId, trigger: 'change' }],
},
}
}
}

由于业务需要在切换公司类型的时候清空 autocomplete 公司名称 ,我是这样做的:

changeApplyType(){
console.info("into-----changeApplyType---")
//切换公司类型,清空上次输入的公司名称
const kongObj = {
id: "",
erpId: "",
company: ""
};
this.handleSelectCompany(kongObj);
},

这里有个坑:手动执行 handleSelectCompany 方法去清空值,容易出现问题: 当切换公司类型后,能成功清空公司名称。

但出现了问题  ,在输入关键字模糊搜索后,关键字在文本框中不显示,并且选中列表中某项后也在文本框中不显示。

解决办法是:changeApplyType 方法中,this.aduitObj.tmpCompanyName = “";这样清空文本框的值。

但是其他 id 值没被清空,还是上一次选择的,在提交的时候随便输入一个名字,没选择,对应的 id 是有值的,还能提交,这就是另外一个 bug 了。

又或者是如果第一次搜索”北京“,出来北京的列表,选择”北京美丽安全有限公司“后,再次把”美丽安全有限公司“删掉,在弹出的列表中没选择,直接点击旁边,隐藏了列表,再点击提交按钮。仍然能提交成功,且保存的名字和 id 是北京美丽安全有限公司的,跟文本框显示出来的北京又不符合了。

于是打算在规则必填项校验 checkCompanyId 方法里面加个:

else if(this.aduitObj.status==1 && !!value && !!this.aduitObj.authCompanyId && value!=this.aduitObj.authCompanyName){

return callback(new Error(‘请重新搜索并选择认证公司!’));

}

这样加上后,提交的时候,校验 tmpCompanyName 名称和上次选中的 authCompanyName 名称不一致就提示,貌似解决了这个问题。

但又出现新的问题,打开 dialog 中首次输入公司,查询出来的列表。当关闭 dialog 后,再次打开别的记录 dialog 后,什么也没输入,点击上去,就直接展示出上次历史查询出来的列表。

想要清空掉历史记录,只能手动调用 fetch-suggestions 接收函数的方法

,让其在关闭 dialog 或打开 dialog 的时候清空历史列表。可是这个方法接收 2 个参数,第一个是查询的字符串,第二个是 callback 函数。这个 callback 函数不知道传递啥才能 自动调用 autocomplete 组件

到此为止,陷入深深的迷茫中。

在别的同事的帮助下,选择 el-select 远程搜索组件解决问题。

使用方法是:

<el-select
v-model="aduitObj.tmpCompanyObj"
value-key="id"
filterable
remote
placeholder="模糊搜索公司名称"
:remote-method="queryCompanyAsync"
@change="toSelectCompany"
:loading="mhLoading" style="width:90%">
<el-option
v-for="item in mhCompanyList"
:key="item.id"
:label="item.company"
:value="item">
</el-option>
</el-select>

请注意因为 select 选择选中一般是值,我这里需要的是选中对象。因为要给其他属性赋值。

这里有个坑:  最开始我没有加 value-key,出现了问题“当模糊搜索选中某值的时候,所有的值都会被自动选中,显示蓝色,并且文本框中默认显示最后一个被选中的值”。解决办法是加 value-key,我最开始以为加在 el-option 上。试验后不行,最终发现是要加在 el-select 上。

这里需要 List 列表,也就是 queryCompanyAsync 远程查询到的列表直接赋值给 option 的 list 即可。

el-select 也会出现跟 el-complete 一样,记录上一次搜索的历史记录的问题。只需要在切换公司的时候,清空列表即可。

changeApplyType(){
console.info("into-----changeApplyType---")
//切换公司类型,清空上次输入的公司名称
const kongObj = {
id: "",
erpId: "",
company: ""
};
// this.handleSelectCompany(kongObj);
// this.aduitObj.tmpCompanyName = "";
this.$set(this.aduitObj, "tmpCompanyObj", kongObj);
	this.mhCompanyList = [];
},

**这里有个坑,直接设置tmpCompanyObj为一个空对象,是不生效的。this.aduitObj.tmpCompanyObj = {

id: “”,

erpId: “”,

company: "”

};**

要使用this.$set 的方式才生效。

要使用:this.$set(this.aduitObj, “tmpCompanyObj”, kongObj);

还有一个巨坑的地方:

在打开编辑dialog回显值的时候,

对于非文本框/非select标准下拉等组件,对对象的某属性直接赋值都无效。需要使用  this.$set 的方式。

<el-form-item label="审核意见:">
<el-input type="textarea" v-model="aduitObj.reviewOpinions"></el-input>
</el-form-item>

//审核意见 回显值
let yijian = this.aduitObj.reviewOpinions ||  this.aduitObj.reviewComments;
this.$set(this.aduitObj, "reviewOpinions", yijian);

========================================

<el-form-item prop='applyType'>
<el-select v-model="aduitObj.applyType" placeholder="请选择" @change="changeApplyType">
<el-option label="客户" value="1"></el-option>
<el-option label="经销商" value="2"></el-option>
</el-select>
</el-form-item>

this.aduitObj.applyType = this.aduitObj.applyType ? this.aduitObj.applyType+"" : "";

在取消 dialog 中:

resetAduitForm(formName){//取消 审核

this.$refs[formName].resetFields();//重置验证消息

this.mhCompanyList = [];//模糊搜索公司名称结果集

this.aduitDialog = false;//审核对话框隐藏

},

这是我开发中遇到的问题的回忆录。

如大侠们有更好的解决方案,还请大侠们多多提点,欢迎发表不同观点,多多留言。