做搜索框的历史记录时遇到的问题?

作者站长头像
站长
· 阅读数 25

1.做搜索框的历史记录的时候 历史记录是搜索框聚焦时且没有内容时展示然后点击历史记录的某一条会把这个记录给input然后触发搜索 肯定也会关闭历史记录 但是点击历史记录的时候 触发了input的失焦 然后历史记录点击事件不生效了尝试过点历史记录的时候 给300延迟关闭历史记录 感觉体验不好 也试过历史记录给透明度0 但是关闭了也能点着肯定是不用说的 所以问下大佬们有什么解决方法吗2.还有个问题是 search组件点清除图标的时候 它是算清空输入框并且失焦的 触发了onChange 然后满足了搜索框没有内容展示 但是它会自动失焦 (失焦在前 onChange在后) 最后用了个开关 点击了清除图标 开关设置true onChange的时候开关为true仍然不给展示感觉是很笨的方法(可能是本身实现思路就不大好) 所以虽然有效但是期待更好的方法和思路

回复
1个回答
avatar
test
2024-06-20

更新:问题一:加一个容器元素把inputul包起来,ref要加到容器上。

问题二:在clean元素的点击事件中控制ul的显示。


我的做法是,不要依赖blur事件。

代码很简单,有不明白的可以问我。

import React, { useRef, useState, useEffect } from 'react';

import './style.css';

const options = [
  {
    id: 1,
    name: '1',
  },
  {
    id: 2,
    name: '2',
  },
  {
    id: 3,
    name: '3',
  },
];

function App() {
  const containerRef = useRef(null);
  const [visible, setVisible] = useState(false);

  // 点击历史记录区域外,关闭历史记录
  useEffect(() => {
    const onClickOutside = (event) => {
      if (
        containerRef.current &&
        !containerRef.current.contains(event.target)
      ) {
        setVisible(false);
      }
    };
    document.addEventListener('mousedown', onClickOutside);
    return () => {
      document.removeEventListener('mousedown', onClickOutside);
    };
  }, [containerRef]);

  const onFocus = () => {
    console.log('onFocus');
    setVisible(true);
  };

  const onClick = () => {
    // 选项被点击后,手动关闭历史记录 掌控权在你手中
    setVisible(false);
  };

  const onClean = () => {
    setVisible(false);
  };

  return (
    <div>
      <h1>stackblitz</h1>
      <div ref={containerRef}>
        <input type="text" onFocus={onFocus} />
        <button onClick={onClean}>clean</button>
        <ul style={{ display: visible ? 'block' : 'none' }}>
          {options.map((item) => (
            <li className="item" onClick={onClick} key={item.id}>
              {item.name}
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default App;
// style.css
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 1rem;
  font-family: system-ui, sans-serif;
  color: black;
  background-color: white;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.item {
  cursor: pointer;
  background: #ccc;
  border-bottom: 1px solid #eee;
}

vue的版本

<script setup>
import { ref } from 'vue';

const visible = ref(false);

const options = [
  {
    id: 1,
    name: '1',
  },
  {
    id: 2,
    name: '2',
  },
  {
    id: 3,
    name: '3',
  },
];

const hideSelct = () => {
  visible.value = false;
};

const onFocus = () => {
  visible.value = true;
};

const onClick = () => {
  hideSelct();
};

const onClean = () => {
  hideSelct();
};

const vClickOutside = {
  mounted(el, binding) {
    const clickOutsideEvent = (event) => {
      if (!el.contains(event.target)) {
        binding.value();
      }
    };

    document.addEventListener('mousedown', clickOutsideEvent);
  },
  unmounted(el) {
    document.removeEventListener('mousedown', clickOutsideEvent);
  },
};
</script>

<template>
  <div v-click-outside="hideSelct">
    <input type="text" @focus="onFocus" />
    <button @click="onClean">clean</button>
    <ul v-show="visible">
      <li v-for="option in options" :key="option.id" @click="onClick">
        {{ option.name }}
      </li>
    </ul>
  </div>
</template>

<style>
* {
  padding: 0;
  margin: 0;
}

body {
  padding: 20px;
}

ul {
  list-style: none;
  background: #ccc;
}

li {
  cursor: pointer;
  padding: 5px;
}
</style>
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容