You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React类组件中Antd Modal滚动至底部启用同意按钮方案问询

解决Ant Design Modal滚动到底部才启用同意按钮的问题

核心思路

Ant Design的Modal组件本身不支持直接传入ref,但你设置的bodyStyle={{ height: '400px', overflowY: 'auto'}}是作用于Modal内部的内容容器,实际滚动的是这个容器。所以我们可以给包裹条款文本的div添加ref,通过监听这个容器的滚动事件,判断是否滚动到底部,从而控制按钮的禁用状态。

修改后的完整代码

import React, { Component } from 'react';
import { Modal, Button } from 'antd';

class TermsModal extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      agreeTerm: true // 初始禁用按钮
    };
    // 创建内容容器的ref
    this.contentRef = React.createRef();
  }

  handleScroll = () => {
    const container = this.contentRef.current;
    if (!container) return;
    // 判断是否滚动到底部:留10px误差兼容不同浏览器滚动精度
    const isBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 10;
    this.setState({
      agreeTerm: !isBottom // 滚动到底部则启用按钮(agreeTerm设为false)
    });
  };

  componentDidUpdate(prevProps, prevState) {
    // Modal从关闭变打开时,添加滚动监听
    if (!prevState.visible && this.state.visible) {
      this.contentRef.current?.addEventListener('scroll', this.handleScroll);
    }
    // Modal从打开变关闭时,移除监听并重置状态
    if (prevState.visible && !this.state.visible) {
      this.contentRef.current?.removeEventListener('scroll', this.handleScroll);
      this.setState({ agreeTerm: true });
    }
  }

  componentWillUnmount() {
    // 组件卸载时清理监听,避免内存泄漏
    this.contentRef.current?.removeEventListener('scroll', this.handleScroll);
  }

  // 示例:打开Modal的触发方法
  openModal = () => {
    this.setState({ visible: true });
  };

  render() {
    return (
      <>
        <Button onClick={this.openModal}>查看条款</Button>
        <Modal 
          title={<h1><b>Terms and Conditions</b></h1>}
          open={this.state.visible}
          width={800}
          bodyStyle={{ height: '400px', overflowY: 'auto'}}
          closable={false}
          footer={                    
            <Button 
              type="primary"
              disabled={this.state.agreeTerm}
              onClick={() => this.setState({ visible: false })}
            >
              Accept
            </Button>
          }
          onCancel={() => this.setState({ visible: false })}
        >
          {/* 给包裹条款的div绑定ref */}
          <div ref={this.contentRef}>
            {/* 此处替换为你的实际条款内容 */}
            <p>条款内容段落1...</p>
            <p>条款内容段落2...</p>
            {/* 省略大量条款内容 */}
            <p>条款内容最后一行...</p>
          </div>
        </Modal>
      </>
    );
  }
}

export default TermsModal;

关键说明

  1. ref绑定目标:将ref绑定到Modal内部的内容div,而非Modal组件本身,因为这个div才是实际产生滚动的容器。
  2. 监听时机控制:仅在Modal打开时添加滚动监听,关闭时立即移除,避免无效监听占用资源。
  3. 滚动判断逻辑:通过scrollTop + 容器可视高度 >= 内容总高度 - 10判断是否触底,减去10px是为了兼容不同浏览器的滚动精度差异,提升用户体验。
  4. 状态重置:Modal关闭时重置按钮禁用状态,确保下次打开Modal时按钮保持初始禁用状态。

内容的提问来源于stack exchange,提问作者The_elevator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:25:21