背景
开发中有时会遇到搜索框没有合适位置摆放的情况,这时就需要通过一个按钮进行展开的搜索框。
- 效果如下
点击按钮时展开搜索框,输入框失焦后关闭搜索框。
实现过程
废话不多说直接上代码
<template>
<div ref="searchWrapper" class="search-wrapper">
<transition name="expand" @after-leave="handleAfterLeave">
<el-input
v-show="isActive"
ref="inputRef"
v-model="searchText"
placeholder="请输入"
class="search-input"
@keyup.enter.native="handleSearch"
>
<el-button
slot="append"
type="primary"
icon="el-icon-search"
circle
@click="handleSearch"
/>
</el-input>
</transition>
<transition name="fade">
<el-button
v-show="isButtonVisible"
class="open-search"
type="primary"
icon="el-icon-search"
@click="toggleSearch"
/>
</transition>
</div>
</template>
<script>
export default {
name: "SearchButton",
props: {
value: {
type: String,
default: ""
}
},
data() {
return {
isButtonVisible: true,
isActive: false
};
},
computed: {
searchText: {
get() {
return this.value;
},
set(value) {
this.$emit("input", value);
}
}
},
mounted() {
document.addEventListener("click", this.handleClickOutside);
},
beforeDestroy() {
document.removeEventListener("click", this.handleClickOutside);
},
methods: {
handleSearch() {
this.$emit("search");
},
/**
* 点击外部区域关闭搜索框
*/
handleClickOutside(event) {
if (this.isActive && !this.$refs.searchWrapper.contains(event.target)) {
this.toggleSearch();
this.searchText = "";
}
},
handleAfterLeave() {
this.isButtonVisible = true; // 当expand动画结束后,显示按钮
},
toggleSearch() {
this.isActive = !this.isActive;
if (this.isActive) {
this.$nextTick(() => {
this.$refs.inputRef.focus();
});
this.isButtonVisible = false; // 当输入框激活时,不显示按钮
}
}
}
};
</script>
<style lang="less" scoped>
.search-wrapper {
border-radius: 10px;
width: 233px;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
/deep/ .el-input__inner {
border-radius: 30px;
height: 45px;
padding: 0 45px 0 15px;
}
/deep/ .el-input-group__append {
color: #fff;
border: none;
padding: 0;
background-color: transparent;
.el-button {
margin: -8px -43px;
border-radius: 50%;
padding: 12px;
}
}
/deep/ .el-input__suffix {
right: 45px;
}
.open-search {
border-radius: 3px;
position: absolute;
}
}
.expand-enter-active,
.expand-leave-active {
transition: transform 0.4s ease-in-out, opacity 0.4s ease-in-out;
transform-origin: right center;
}
.expand-enter,
.expand-leave-to {
transform: scaleX(0.2);
opacity: 0;
}
.expand-enter-to,
.expand-leave {
transform: scaleX(1);
opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
transition: transform 0.1s ease-in-out;
}
.fade-enter,
.fade-leave-to {
transform: scaleX(0);
}
</style>