更新:
问题一:
加一个容器元素把"input"和"ul"包起来,"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 (
stackblitz
clean
{options.map((item) => (
{item.name}
))}
);
}
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的版本
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);
},
};
clean
{{ option.name }}
* {
padding: 0;
margin: 0;
}
body {
padding: 20px;
}
ul {
list-style: none;
background: #ccc;
}
li {
cursor: pointer;
padding: 5px;
}