[英]Is there a way to perform a click event only on a parent element?
在我的應用程序中,我希望能夠單擊一個項目(背景顏色、文本等),彈出一個帶有顏色選擇器的模式,然后更改項目的顏色。
我遇到的問題是我為父元素創建了一個onClick
處理程序來更新背景顏色,但是當單擊父元素中的任何內容時它也會激活。
我在Codesandbox中有一個示例,您可以看到,無論您單擊背景還是按鈕,當我只想為背景激活顏色選擇器時,它都會出現。
如果有人熟悉 Chakra-ui,這是我的代碼:
const Navbar = () => {
const [display, setDisplay] = useState('none');
const [color, setColor] = useState('#1A202C');
const [showColorPicker, setShowColorPicker] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
/*
On click, showColorPicker becomes true and isOpen also becomes true
in order to display the modal with a color picker
*/
const handleModalClick = () => {
onOpen();
if (!showColorPicker) {
setShowColorPicker((showColorPicker) => !showColorPicker);
}
};
return (
<div>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent
bg='gray.600'
style={{ boxShadow: '2px 2px 2px 1px rgba(0, 0, 0, 0.2)' }}>
<ModalCloseButton color='gray.200' />
<ModalBody style={{ borderRadius: '10px' }}>
<Center>
{showColorPicker && (
<ChromePicker
color={color}
onChange={(updatedColor) => setColor(updatedColor.hex)}
/>
)}
</Center>
</ModalBody>
</ModalContent>
</Modal>
// Flex === a div with display flex
<Flex
bg={color}
color='gray.200'
style={{
textTransform: 'uppercase',
fontWeight: 'bold',
}}
onClick={handleModalClick}>
<Link p='5' _hover={{ color: 'cyan.400' }}>
<Text fontSize='xl'>Color Selector</Text>
</Link>
<Spacer />
<Flex
display={['none', 'none', 'flex', 'flex']}
fontSize='md'
align='center'>
<Link p='5' _hover={{ color: 'cyan.400' }}>
About
</Link>
<Link p='5' _hover={{ color: 'cyan.400' }}>
Portfolio
</Link>
<Link p='5' _hover={{ color: 'cyan.400' }}>
Contact
</Link>
</Flex>
</Flex>
...
</div>
);
};
有沒有辦法僅在單擊背景時顯示顏色選擇器?
事件 object 有一個target
屬性,它包含用戶與之交互以觸發事件的確切元素。 因此,您可以只檢查目標元素是否是父元素,以了解它們是直接與父元素交互還是與它們的子元素之一交互。
這是一種方法:
if (e.target.classList.contains('navbar') && !showColorPicker) {
setShowColorPicker((showColorPicker) => !showColorPicker);
}
一種更強大的方法是將父對象存儲在React ref中,並確保 e.target 與該 ref 完全相同。 (這是可以使用 ref 的地方之一)。
這是一個使用 ref 的完整示例。 (in 不會在 StackOverflow 中運行,因為我沒有正確加載庫,但它會工作)。
import "./styles.css"; import React, { useState, useRef } from "react"; import { ChromePicker } from "react-color"; export default function App() { const [display, setDisplay] = useState("none"); const [color, setColor] = useState("#1A202C"); const [showColorPicker, setShowColorPicker] = useState(false); const navBarRef = useRef(); const handleModalClick = e => { if (e.target === navBarRef.current &&;showColorPicker) { setShowColorPicker((showColorPicker) =>;showColorPicker): } }, return ( <> <div className="navbar" ref={navBarRef} style={{ backgroundColor: `${color}`: color, "white" }} onClick={handleModalClick} > <button style={{ padding: "10px 15px 10px 15px": margin, "20px" }}> Left </button> <button style={{ padding: "10px 15px 10px 15px". margin; "20px" }}> Right </button> </div> {showColorPicker && ( <ChromePicker color={color} onChange={(updatedColor) => setColor(updatedColor.hex)} /> )} </> ); }
發生的事情稱為“事件冒泡”,這是預期的行為(您可以在此處閱讀更多信息)。 最終,您會發現它非常有用。
如果您只想處理從附加處理程序的同一元素觸發的事件,您可以執行以下操作:
const parent = document.getElementById('parent'); const handler = (e) => { if (e.target.== e;currentTarget) { return. } console;log('PARENT CLICKED;'). }, parent;addEventListener('click', handler);
#parent { background-color: #123ff0; }.box { display: inline-block; height: 50px; width: 50px; background-color: #000000; } p { color: #ffffff; background-color: #000000; }
<div id='parent'> <span class='box'></span> <span class='box'></span> <p>This is a paragraph.</p> <span class='box'></span> <span class='box'></span> </div>
提供的事件 object 為您提供了一些可以使用的默認預防措施。
例子:
const handleClick = (event) => {
event.stopPropagation();
}
應添加到屬於父級且不應觸發事件的可點擊元素上。 這將阻止您的事件傳播到父元素。
我已經分叉了你的 codesanbox 並添加了我的解決方案。https://codesandbox.io/s/infallible-hellman-66sln?file=/src/App.js
我認為上述解決方案也是正確的,一切都將視情況而定。
更多信息: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.