繁体   English   中英

有没有办法只在父元素上执行点击事件?

[英]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>
  );
};

有没有办法仅在单击背景时显示颜色选择器?

如果您想查看GitHub上的真实示例或所有代码,该应用程序也部署在Netlify上。

事件 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM