google搜索框

这是一个非常敏锐的发现。导致你"点击外部没有收起"的原因,是我在上一段代码的 handleBlur 中加了一句判断:if(!query.value) ...。这导致了只有在输入框为空时才会收起,如果有文字内容则保持展开。

为了完全实现你描述的 Google 效果(无论是否有内容,点击外部区域必须收起为一行,点击内部展开 ),单纯依靠 blur 事件经常会遇到坑(比如你想点击输入框旁边的"搜索"按钮,结果 blur 先触发把输入框收起了,导致按钮点击失效)。

最稳健、大厂通用的做法是使用 Element Plus 自带的 v-click-outside 指令

下面是修复后的完整代码,它解决了两个核心问题:

  1. 交互逻辑 :使用 ClickOutside 精准判断点击行为,点击外部必收起。
  2. 样式切换 :利用 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>

为什么这样做更好?

  1. 解决了 blur 的冲突

    如果你用 blur 事件,当你试图点击输入框旁边的"搜索"按钮时,浏览器流程是:Input Blur -> Wrapper收起 -> Button Click

    因为 Wrapper 瞬间收起,按钮可能移位了或者消失了,导致点击无效。

    使用 v-click-outside,点击搜索组件内部(包括按钮)都不会触发收起,只有点击真正的"外部"才会收起,体验最流畅。

  2. 解决了 el-input 的换行残留问题
    el-inputtextarea 模式默认是不支持单行省略号(text-overflow: ellipsis)的。

    通过 :type="isExpanded ? 'textarea' : 'text'" 动态切换:

    • 未激活时 :它是标准的单行文本框,内容过长自动显示 ...
    • 激活时:它是多行文本域,内容完整展示并把框撑大。

你可以把这段代码替换进去,现在的效果应该是:

  1. 鼠标点进去 -> 框变大(盖住下面的表格),显示多行。
  2. 鼠标点表格或分页 -> 框瞬间变回单行,表格内容正常点击。
相关推荐
小飞侠在吗11 小时前
vue computed 和 watch
前端·javascript·vue.js
毕设十刻11 小时前
基于Vue的考勤管理系统8n7j8(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
CPU NULL13 小时前
Vue 3 前端调试与开发指南
前端·javascript·vue.js
老华带你飞14 小时前
社团管理|基于Java社团管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
十一.36614 小时前
83-84 包装类,字符串的方法
前端·javascript·vue.js
码农阿豪15 小时前
Vue项目构建中ESLint的“换行符战争”:从报错到优雅解决
前端·javascript·vue.js
老华带你飞15 小时前
汽车销售|汽车报价|基于Java汽车销售系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·后端·汽车
xhxxx16 小时前
AI打字机的秘密:一个 buffer 如何让机器学会“慢慢说话”
前端·vue.js·openai
Irene199116 小时前
在 Vue 3 中使用 工作者线程
vue.js·工作者线程