search组件(vite5+vue3.4)

60 阅读1分钟

search组件分析

Snipaste_2025-02-05_10-10-26.png

聚焦input时会显示弹出层,点击按钮会触发事件

代码

<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'
const model = defineModel()
// 搜索功能
const emits = defineEmits(['search'])
const onSearch = () => {
  emits('search', model)
}
// 聚焦
const isFocus = ref(false)
const onFocus = () => {
  isFocus.value = true
}
//隐藏下拉菜单
const containerTarget = ref(null)
onClickOutside(containerTarget, () => {
  isFocus.value = false
})
</script>

<template>
  <div
    ref="containerTarget"
    class="group relative p-0.5 roundedxl border-white duration-500 hover:border-red-100/40">
    <!-- 放大镜 -->
    <m-svg-icon
      class="w-1.5 h-1.5 absolute translate-y-[-50%] top-[50%] left-2"
      name="search"
      color="#707070" />
    <input
      @focus="onFocus"
      class="block w-full h-[44px] pl-4 text-sm outline-0 bg-zinc-100 caret-zinc-400 rounded-xl text-zinc-900 tracking-wide font-semibold border border-zinc-100 duration-500 group-hover:bg-white group-hover:border-zinc-200 focus:border-red-300"
      type="text"
      placeholder="搜索"
      v-model="model" />
    <!-- 删除 -->
    <m-svg-icon
      v-show="model"
      @click="model = ''"
      name="input-delete"
      class="h-1.5 w-1.5 absolute translate-y-[-50%] top-[50%] right-9 duration-500 cursor-pointer"></m-svg-icon>
    <!-- 分割线 -->
    <div
      class="opacity-0 h-1.5 w-[1px] absolute translate-y-[-50%] top-[50%] right-[62px] duration-500 bg-zinc-200 group-hover:opacity-100"></div>
    <!--搜索按钮(通用组件) -->
    <m-button
      @click="onSearch"
      class="absolute translate-y-[-50%] top-[50%] right-1 bg-red-400 hover:bg-red-500 active:bg-red-600"
      icon="search"
      iconColor="#ffffff"></m-button>
    <!-- 下拉菜单 -->

    <transition name="slide">
      <div
      v-if="$slots.dropdown" 
        v-show="isFocus"
        class="group max-h-[368px] w-full text-base overflow-auto bg-white absolute z-20 left-0 top-[56px] p-2 rounded border border-zinc-200 duration-200 hover:shadow-3xl">
        <slot name="dropdown" />
      </div>
    </transition>
  </div>
</template>

<style scoped>
.slide-enter-active {
  transition: all 0.5s;
}
.slide-leave-active {
  transition: all.5s;
}
.slide-enter-from,
.slide-leave-to {
  opacity: 0;
  transform: translateY(40px);
}
</style>


知识点:

  • vue3.4的defineModel绑定input
  • emits事件search暴露出去
  • 下拉菜单用插槽展示出口
  • vueUse的onClickOutside方法监听点击dom以外的地方的事件