最近给了一个新需求:输入框既可手动输入又可下拉选择,且下拉框数据来源于点击输入框旁边的搜索按钮后后端传回来的数据,结合前人的经验,用原生代码实现了这个需求,并在此基础上对下拉框样式进行了优化,下拉框缓慢出现动画、阴影效果等。这里把后端传数据等功能抹掉,记录下最原始的实现过程,最终效果如下图
涉及到多处使用到这个输入框,所以将其封装成一个组件。
使用到的工具:一个input输入框,一个三角图标,ul+li实现下拉框。
<template>
<div class="SelectInput">
<div class="sel-inp">
<input type="text" class="inp" v-model="inpValue" placeholder="请输入" />
<img
src="../../assets/select_triangle_up.png"
class="turn-img"
:class="{ turnUp: showList, turnDown: !showList }"
@click="showList = !showList"
height="44"
width="44"
/>
</div>
<!-- 下拉框数据 -->
<ul
class="list"
:class="{ open: this.showList, close: !this.showList }"
v-if="this.list.length"
>
<li
v-for="(item, index) in list"
:key="index"
class="list-item"
:class="{ active: index === currentIndex }"
@click="handleClick(index, item)"
>
{
{ item.value }}
</li>
</ul>
<!-- 无数据时显示-->
<ul
class="list"
:class="{ open: this.showList, close: !this.showList }"
v-if="!this.list.length"
>
<li class="list-item">暂无数据</li>
</ul>
</div>
</template>
伪装的下拉框样式实现:使用定位将三角图标定位到输入框右边。
.turn-img {
position: absolute;
top: 0;
right: 0;
}
下拉框收起与展开控制:首先在data里定义一个布尔值showList来控制下拉框的展开与收起,使用动态class来实现三角图标旋转动画。
.turnUp {
transform: rotate(180deg);
transition-duration: 0.2s;
}
.turnDown {
transition-duration: 0.2s;
}
下拉框使用定位定在输入框下方,下拉框缓慢出现使用maxheight和transition实现,当下拉框收起时将maxheight设为0,并将超出的内容隐藏掉,下拉框展开时将maxheight设为一个固定值,并加上过渡和阴影,就不会显得那么突兀。
.list {
max-height: 0;
overflow: hidden;
z-index: 999;
background-color: white;
position: absolute;
top: 27px;
left: 0;
list-style-type: none;
padding: 0;
.list-item {
display: flex;
align-items: center;
width: 240px;
height: 44px;
font-size: 18px;
color: #1f242a;
text-align: left;
padding-left: 10px;
border-left: 1px solid #e4e7ed;
border-right: 1px solid #e4e7ed;
border-bottom: 1px solid #e4e7ed;
cursor: pointer;
}
.list-item:first-child {
border-top: 1px solid #e4e7ed;
}
}
.open {
max-height: 500px;
transition: max-height 0.5s;
box-shadow: 0 5px 5px 3px #dde3e9;
}
.close {
max-height: 0;
transition: max-height 0.2s;
}
鼠标经过和选中样式:这里注意hover样式要将选中的项排除在外
.active {
background-color: #0092ff;
color: white;
}
.list-item:hover:not(.active) {
background-color: #f5f7fa;
}
最后,处理一下li上的点击事件,将值赋给输入框绑定值即可。
handleClick(index, item) {
this.currentIndex = index;
this.showList = false;
this.inpValue = item.value;
}
这样就实现了一个最基本的即可输入又可下拉选择的输入框了。
缺陷:在实现下拉框缓慢展开的时候,先是将maxheight设为0,再将溢出内容隐藏,展示下拉框时,再设置maxheight,如果展示的数据是动态的,则不能确定下拉框的长度,设置太小那么部分内容被隐藏,设置太大效果不好。也尝试过其他缓慢展开的方式,但达不到这种从上往下缓慢展开的效果,也可能因为我接触前端不久,没接触到更好的办法,大家如果有更好的建议欢迎评论区交流指正。