这是一个非常敏锐的发现。导致你"点击外部没有收起"的原因,是我在上一段代码的 handleBlur 中加了一句判断:if(!query.value) ...。这导致了只有在输入框为空时才会收起,如果有文字内容则保持展开。
为了完全实现你描述的 Google 效果(无论是否有内容,点击外部区域必须收起为一行,点击内部展开 ),单纯依靠 blur 事件经常会遇到坑(比如你想点击输入框旁边的"搜索"按钮,结果 blur 先触发把输入框收起了,导致按钮点击失效)。
最稳健、大厂通用的做法是使用 Element Plus 自带的 v-click-outside 指令。
下面是修复后的完整代码,它解决了两个核心问题:
- 交互逻辑 :使用
ClickOutside精准判断点击行为,点击外部必收起。 - 样式切换 :利用
type属性的动态切换,实现"收起时是单行(自动省略号),展开时是多行(自动增高)"。
修复后的代码 (Vue 3 + Composition API)
html
<template>
<div
class="search-container"
v-click-outside="onClickOutside"
>
<div class="placeholder"></div>
<div class="search-input-wrapper" :class="{ 'is-expanded': isExpanded }">
<el-input
v-model="query"
:type="isExpanded ? 'textarea' : 'text'"
:autosize="isExpanded ? { minRows: 2, maxRows: 6 } : false"
placeholder="请输入内容"
@focus="onFocus"
>
<template #suffix>
<el-icon class="el-input__icon"><Search /></el-icon>
</template>
</el-input>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ClickOutside as vClickOutside } from 'element-plus' // 引入指令
import { Search } from '@element-plus/icons-vue'
const query = ref('这是一段很长的测试文本,用来测试当内容过多时,点击外部是否会正确收起变成单行省略号显示,点击内部是否会展开显示全部内容。')
const isExpanded = ref(false)
// 聚焦时展开
const onFocus = () => {
isExpanded.value = true
}
// 点击外部区域时收起
const onClickOutside = () => {
// 可以在这里加逻辑:如果输入框是空的,可能不需要特殊处理
isExpanded.value = false
}
</script>
<style scoped>
.search-container {
position: relative;
height: 40px; /* 这里的 40px 要和 el-input 的默认高度一致 */
z-index: 100; /* 确保层级够高 */
margin: 20px;
}
.placeholder {
height: 100%;
width: 100%;
}
.search-input-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: white;
transition: box-shadow 0.3s;
border-radius: 4px;
}
/* 展开时的样式增强:加阴影,覆盖下方内容 */
.search-input-wrapper.is-expanded {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
</style>
为什么这样做更好?
-
解决了
blur的冲突 :如果你用
blur事件,当你试图点击输入框旁边的"搜索"按钮时,浏览器流程是:Input Blur->Wrapper收起->Button Click。因为 Wrapper 瞬间收起,按钮可能移位了或者消失了,导致点击无效。
使用
v-click-outside,点击搜索组件内部(包括按钮)都不会触发收起,只有点击真正的"外部"才会收起,体验最流畅。 -
解决了
el-input的换行残留问题 :
el-input的textarea模式默认是不支持单行省略号(text-overflow: ellipsis)的。通过
:type="isExpanded ? 'textarea' : 'text'"动态切换:- 未激活时 :它是标准的单行文本框,内容过长自动显示
...。 - 激活时:它是多行文本域,内容完整展示并把框撑大。
- 未激活时 :它是标准的单行文本框,内容过长自动显示
你可以把这段代码替换进去,现在的效果应该是:
- 鼠标点进去 -> 框变大(盖住下面的表格),显示多行。
- 鼠标点表格或分页 -> 框瞬间变回单行,表格内容正常点击。