为什么节点 contains 方法没有捕获对 svg 元素的点击?

Far*_*ane 7 html javascript svg

我有一个基本的模态,其 html 结构中有一个 svg 图标。我想检测模式之外的点击,以便我可以将其关闭。执行此操作的代码类似于以下内容:

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

但是,当我单击 svg(位于模态内部)时,单击事件被认为位于模态外部,我不明白为什么。为了让它按照我想要的方式工作,我必须对 svg 元素执行pointer-events: none。

简化的 html 结构如下所示:

  <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>
Run Code Online (Sandbox Code Playgroud)

编辑:如果我在此处粘贴实际的反应代码,也许会有所帮助,因为我不确定它是否是 svg 元素而不是我的代码的问题。

    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>
  );
});
Run Code Online (Sandbox Code Playgroud)

Far*_*ane 4

我只是明白发生了什么,这与 svgs 无关。发生的情况是,当我单击 svg 时,首先会触发“mousedown”事件。请记住,“单击”事件由两个相继发生的事件组成:第一个是“鼠标按下”,然后是“鼠标松开”。

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

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