近况
哎呀呀,也是好久好久没有更新博客,一个是因为需求太多,另一个是因为太懒(哈哈,这个是主要原因),最近都在做Element的需求,因为是之前的项目,vue3和Element-Plus也还没开始用,准备多学习学习在小项目上练练手。
需求
好啦废话不多说啦,最近接到这么一个需求,在基础的饿了么的选择器中加入头像,姓名,描述等信息。大致就是这样样子:
看到这里并没有什么问题,因为select
组件是支持自定义options
的样式的。无良的产品要求选择完之后要在输入框里也显示头像,类似这个效果:
WTF,真是想分分钟想提刀的节奏。但是气归气,但是又无法拒绝,所以只能默默地打开了度娘。搜了一圈是之后也没发现啥有用的东西,哎,还是自己来吧。
实现思路
- 如何在
input
框内还能显示img图片呢?
我的思路就是用一个div
绝对定位在input
内,在select
的change事件中触发,并且用自己写的一个input来遮盖el-select
组件,达到以假乱真的效果。 - 多选如何实现?
el-selcet
组件是支持多选的,所以选择的事件不是很难,比较麻烦的是要自己去定义每个item的样式和删除功能。 - 多选带来的样式问题?
在选择多个达到两行的时候,所选择的人物会超过原来input
的高,会导致样式错误,我的思路是监听选择人物数量的同时去获取选择人物div
的高,将它的高赋值给input
。
具体实现
- 隐藏
el-select
原有样式,只是隐藏并不是display:none
哦,用自己的input覆盖样式。
注意看,el-select
是被我visibility: hidden;
隐藏掉了并且定位到我自己写的input
下。
- 点击自己画的
input
的时候来触发el-selcet
的下拉框弹出事件
this.$refs.select.handleFocus();
- 在
el-select
的change事件中做处理
handleSelectChange(v) {
this.form.queryStaff = v;
this.inputValue = "";// input内输入的值
this.form.queryStaffPlaceholder = v.name; //input的placeholder
this.isShowUserInfo = true;//是否显示头像信息
this.$refs.form.validateField("queryStaff"); //触发一次表单验证
},
注意:因为我们不止要拿到选择的姓名,所以el-select
绑定的value应该是对象,并且设置value-key="id"
,才能完成对对象的绑定。
- 多选的时候遇到样式错乱的解决办法
watch: {
"form.enjoypeople": {
handler(val) {
if (val.length) {
this.$nextTick(() => {
let height = this.$el.querySelector(".form1-tag").clientHeight;
this.$refs.input_enjoy_dryform1.style.height =
height > 4
? this.$el.querySelector(".form1-tag").clientHeight + 4 + "px"
: 32 + "px";
});
}
},
deep: true,
},
}
具体代码(多选为例):
<div class="record-meeting__elinput">
<div class="el-input_dry">
<input
ref="input_enjoy_dry"
@focus="handleQueryMutipleStaffFocus"
@click.stop="handleQueryEnjoyClick"
@blur="handleQueryMutipleStaffBlur"
:placeholder="
form.enjoypeople1.length ? '' : '请选择AI人员'
"
v-model="inputMultipleValue"
/>
<div
class="multiple-tag form-tag"
style="bottom: 0px;top:auto; "
@click="handleMutipleStaffClick"
v-if="isShowUserMultipleInfo"
>
<div
v-for="(item, index) in form.enjoypeople1"
:key="index"
class="multiple-tag__item"
>
<img
:src="
item.personFiles.length
? item.httpUrl + item.personFiles[0].fileurl
: require('@/assets/img/user.png')
"
/>
<span>{{ item.name }}</span>
<i
class="el-tag__close el-icon-close"
@click.stop="handleMultipleDel(index)"
></i>
</div>
</div>
</div>
<el-select
v-model="form.enjoypeople"
multiple
ref="selcet_enjoy"
filterable
remote
reserve-keyword
value-key="id"
@change="handleSelectMutipleChange"
v-loadmore="handleenjoyPopupScroll"
:remote-method="remoteMethodsearchpeople"
placeholder="请选择参会人"
style="width:320px;position: absolute;
display: block;visibility: hidden;height:0;bottom: 184px;"
:loading="loading"
>
<el-option
v-for="(item, index) in curSelectOptionssearchpeople"
:key="index"
:label="item.name"
:value="item"
>
<div class="select-item">
<img
:src="
item.personFiles.length
? item.httpUrl + item.personFiles[0].fileurl
: require('@/assets/img/user.png')
"
/>
<div>
<p>{{ item.name }}</p>
<p :title="item.description">{{ item.description }}</p>
</div>
</div>
</el-option>
</el-select>
</div>
//点击出现下拉框
handleQueryEnjoyClick() {
this.$refs.selcet_enjoy.handleFocus();
},
handleSelectMutipleChange(v) {
this.inputMultipleValue = "";
this.isShowUserMultipleInfo = true;
},
//input Focus 事件
handleQueryMutipleStaffFocus() {
if (!this.form.enjoypeople.length) {
//为了避免触发两次出现弹框
return;
}
this.isShowUserMultipleInfo = false;
this.handleQueryEnjoyClick();
},
//点击删除事件
handleMultipleDel(index) {
this.form.enjoypeople.splice(index, 1);
},
//失焦事件 如果有之前有选择的内容,显示选择的内容
handleQueryMutipleStaffBlur() {
if (this.form.enjoypeople.length) {
this.isShowUserMultipleInfo = true;
}
},