为什么 node contains 方法没有捕获对 svg 元素的点击? [英] Why a click on svg element is not captured by node contains method?

查看:28
本文介绍了为什么 node contains 方法没有捕获对 svg 元素的点击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本模式,在其 html 结构中带有一个 svg 图标.我想检测模态之外的点击,以便我可以关闭它.执行此操作的代码如下所示:

document.addEventListener('mousedown', (e) => {if(modal.contains(e.target)) 返回;关闭模态();});

但是,当我点击 svg(在模态内)时,点击事件被认为是在模态之外,我不知道为什么.为了让它按我想要的方式工作,我必须对 svg 元素执行指针事件:无.

简化的 html 结构如下所示:

 

<button class="css-1pnrrva";禁用=">验证器</表单>

如果我将实际的 react 代码粘贴在这里,也许会有所帮助,因为我不确定它是否是 svg 元素而不是我的代码的问题.

 export const PasswordInput = React.forwardRef(({占位符,姓名,ID,残疾,班级名称,}: PasswordInputProps, ref) =>{const [showPassword, setShowPassword] = useState(false);const DisplayedPicto = showPassword ?ClosedEyePicto : EyePicto;返回 (<容器类名={类名}><自定义输入类名={类名}类型={显示密码?'文本':'密码'}占位符={占位符}名称={名称}禁用={禁用}参考={参考}id={id}/><样式后缀onMouseLeave={() =>设置显示密码(假)}onMouseDown={() =>设置显示密码(真)}onMouseUp={() =>设置显示密码(假)}id='test-input-toggle-password-visibility'><DisplayedPicto height={16}/>//svg 元素</StyledSuffix></容器>);});

解决方案

我刚刚明白发生了什么,与 svgs 无关.发生的事情是,当我单击 svg 时,首先会触发鼠标按下"事件.请记住,点击"事件由 2 个相互跟随的事件组成:首先是鼠标按下",然后是鼠标抬起".

因此,通过 svg 上的 'mousedown' 事件,触发了围绕我的 svg 的组件 StyledSuffix 上的 onMouseDown 事件处理程序.这导致 dom 上的 svg 实际上从 EyePicto 变为 ClosedEyPicto(const DisplayedPicto = showPassword ? ClosedEyePicto : EyePicto;).因此,模态不再包含"原始 svg,因为它已更改!

一个解决方案是使用事件click"而不是mousedown"来监听点击.因为原始 svg (EyePicto) 只会注册 'mousedown' 事件而不是 'mouseup',因为它从 2 之间的 dom 中消失了.

I have a basic modal with a svg icon within its html structure. I want to detect clicks outside the modal so I can close it. The code to do so is something like the following:

document.addEventListener('mousedown', (e) => {
  if(modal.contains(e.target)) return;
  closeModal();
});

However, when I click on the svg (which inside the modal), the click event is considered to be outside the modal and I can't figure out why. To have it work as I want, I have to do pointer-events: none to the svg element.

The simplified html structure looks like this:

  <div class="modal">
    <div class="css-t7awl3">
      <form>
        <div class="css-1incodr">
          <label class="css-g2pzhe" for="previousPassword">
            Mot de passe actuel<span class="css-5fl39m">*</span>
          </label>
        <div class="css-1xm32e0">
          <input
            class="css-17lan49"
            type="text"
            placeholder="**********"
            name="previousPassword"
          />
            <div id="test-input-toggle-password-visibility" class="css-1vw18kh">
              <svg
                height="16"
                viewBox="0 0 32 32"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              />
            </div>
          </div>
        </div>
        <button class="css-1pnrrva" disabled="">
          Valider
        </button>
      </form>
    </div>
  </div>

Edit: Maybe it can help if I paste the actual react code here, as I am not sure if it's and issue with svg elements rather than my code.

    export const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(({
  placeholder,
  name,
  id,
  disabled,
  className,
}: PasswordInputProps, ref) => {
  const [showPassword, setShowPassword] = useState(false);

  const DisplayedPicto = showPassword ? ClosedEyePicto : EyePicto;

  return (
    <Container className={className}>
      <CustomInput
        className={className}
        type={showPassword ? 'text' : 'password'}
        placeholder={placeholder}
        name={name}
        disabled={disabled}
        ref={ref}
        id={id}
      />
      <StyledSuffix
        onMouseLeave={() => setShowPassword(false)}
        onMouseDown={() => setShowPassword(true)}
        onMouseUp={() => setShowPassword(false)}
        id='test-input-toggle-password-visibility'
      >
        <DisplayedPicto height={16} />  //svg element
      </StyledSuffix>
    </Container>
  );
});

解决方案

I just understood what was going on, and it has nothing to do with svgs. What's happening is that when I click on the svg, first a 'mousedown' event is triggered. Remember that a 'click' event consists of 2 events following each other: first a 'mousedown' and then a 'mouseup'.

So with the 'mousedown' event on the svg, the onMouseDown event handler, on the component StyledSuffix surrounding my svg, is triggered. That leads to the svg on the dom actually changing from EyePicto to ClosedEyPicto (const DisplayedPicto = showPassword ? ClosedEyePicto : EyePicto;). Therefore, the modal no longer 'contains' the original svg since it has changed!

A solution is to listen to the click with the event 'click' rather than with 'mousedown'. Because the orginal svg (EyePicto) will only register the 'mousedown' event and not then 'mouseup' because it disappeared from the dom between the 2.

这篇关于为什么 node contains 方法没有捕获对 svg 元素的点击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆