react 实现点击其他地方,隐藏列表(点击元素外)

前言:

我们经常封装一些自己的下拉列表组件 或者 弹窗组件。一般 点击按钮显示 列表或 弹窗。再次点击 隐藏或关闭,但 ui库里的下拉列表,点击除了自己本身也能实现隐藏对应的列表。下面我就给大家一个实现思路。

弹窗组件可以用 React Portals 实现:react 官网 createPortal

实现步骤:

这是一个 简单的点击按钮,显示列表。再次点击隐藏。但我的需求是,点击其他地方也隐藏。

import React, { ReactNode, useEffect, useState, useRef } from "react";

const MyList = () => {
  const [visable, setVisabled] = useState(false);
  return (
    <div>
      <button onClick={() => setVisabled(!visable)}>点击显示 列表</button>
      <div style={{ display: visable ? "block" : "none" }}>
        <div>11111</div>
        <div>22222</div>
      </div>
    </div>
  );
};
export default MyList;

可以利用contains 结合 ref(建议用ref,当然也可以用 document方法,给元素加个 id) 。
contains 是 DOM 元素的方法,用于确定一个元素是否包含另一个元素。不包含则执行 关闭/隐藏事件。
还需要 注意的是,需要 给 隐藏、显示的点击事件加个 阻止事件冒泡的方法event.stopPropagation();
阻止事件冒泡方法必须加上!!!

代码如下:

import React, { ReactNode, useEffect, useState, useRef } from "react";

const MyList = () => {
  const [visable, setVisabled] = useState(false);
  // 下拉列表 ref
  const dropdownRef = useRef(null);

  useEffect(() => {
    //实现点击 本元素外的元素时,隐藏下拉列表(点击其他地方隐藏下拉列表)
    function handleOutsideClick(event) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
        setVisabled(false);
      }
    }
    document.addEventListener("click", handleOutsideClick);
    return () => {
      document.removeEventListener("click", handleOutsideClick);
    };
  }, []);
  const hanldClick = (event) => {
    event.stopPropagation(); // 阻止事件冒泡
    setVisabled(!visable);
  };
  return (
    <div>
      <button onClick={hanldClick}>点击显示 列表</button>
      <div ref={dropdownRef} style={{ display: visable ? "block" : "none" }}>
        <div>11111</div>
        <div>22222</div>
      </div>
    </div>
  );
};
export default MyList;

核心代码就是这块:
需要注意的是 绑定的事件需要 在 组件卸载时移除。

useEffect(() => {
    //实现点击 本元素外的元素时,隐藏下拉列表(点击其他地方隐藏下拉列表)
    function handleOutsideClick(event) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
        setVisabled(false);
      }
    }
    document.addEventListener("click", handleOutsideClick);
    return () => {
      document.removeEventListener("click", handleOutsideClick);
    };
  }, []);

类组件就是这样:
只是把useEffetc里的内容 转换成Class语法。componentDidMount 绑定事件,componentWillUnmount移除事件。

import React, { Component } from "react";
class MyList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false
    };
    this.dropdownRef = React.createRef(); // 下拉列表 ref
  }
  componentDidMount() {
    // 实现点击本元素外的元素时,隐藏下拉列表(点击其他地方隐藏下拉列表)
    document.addEventListener("click", this.handleOutsideClick);
  }
  componentWillUnmount() {
    document.removeEventListener("click", this.handleOutsideClick);
  }
  handleOutsideClick = (event) => {
    if (
      this.dropdownRef.current &&
      !this.dropdownRef.current.contains(event.target)
    ) {
      this.setState({ visible: false });
    }
  };
  handleClick = (event) => {
    event.stopPropagation(); // 阻止事件冒泡
    this.setState((prevState) => ({
      visible: !prevState.visible
    }));
  };
  render() {
    const { visible } = this.state;
    
    return (
      <div>
        <button onClick={this.handleClick}>点击显示列表</button>
        <div
          ref={this.dropdownRef}
          style={{ display: visible ? "block" : "none" }}
        >
          <div>11111</div>
          <div>22222</div>
        </div>
      </div>
    );
  }
}
export default MyList;

理论上来说 这个思路在 vue里也适用,只需要转化vue语法。不过vue 有指令库 v-clickoutside。

总结:

题外话:现在ai真的很强大,我类组件的写法就是让ai转换的,竟然完全正确,运行无误!!! 如果简单的组件 可以试试 ai 。比如 chatGPT\文心一言\通义千问。

比如:文心给的 就可以用,编程方面 chatGPT会比文心强,目前 我认为 gpt是独一档的强!
文心一言 提问分享

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,关于React Hook实现点击弹窗隐藏弹窗,可以使用useRef和useEffect来实现clickoutside的效果。 首先,在弹窗组件中定义一个ref,用来获取弹窗元素的DOM节点: ```javascript const modalRef = useRef(null); ``` 然后在组件中使用useEffect监听document的点击事件,判断点击位置是否在弹窗,如果是,则隐藏弹窗: ```javascript useEffect(() => { function handleModalClickOutside(event) { if (modalRef.current && !modalRef.current.contains(event.target)) { // 点击弹窗部,隐藏弹窗 hideModal(); } } document.addEventListener('click', handleModalClickOutside); return () => { document.removeEventListener('click', handleModalClickOutside); }; }, [hideModal]); ``` 这样,当点击document的时候,会触发handleModalClickOutside函数,判断点击位置是否在弹窗,如果是,则调用hideModal函数隐藏弹窗。 完整的代码如下: ```javascript import React, { useRef, useEffect } from 'react'; function Modal({ children, hideModal }) { const modalRef = useRef(null); useEffect(() => { function handleModalClickOutside(event) { if (modalRef.current && !modalRef.current.contains(event.target)) { hideModal(); } } document.addEventListener('click', handleModalClickOutside); return () => { document.removeEventListener('click', handleModalClickOutside); }; }, [hideModal]); return ( <div className="modal" ref={modalRef}> {children} </div> ); } export default Modal; ``` 使用的时候,只需要在父组件中传入hideModal函数即可: ```javascript import React, { useState } from 'react'; import Modal from './Modal'; function App() { const [showModal, setShowModal] = useState(false); function handleShowModal() { setShowModal(true); } function handleHideModal() { setShowModal(false); } return ( <div className="app"> <button onClick={handleShowModal}>Show Modal</button> {showModal && ( <Modal hideModal={handleHideModal}> <h1>Modal Content</h1> </Modal> )} </div> ); } export default App; ``` 这样,当点击弹窗部时,会隐藏弹窗

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

崽崽的谷雨

漫漫前端路,摸爬滚打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值