antd的Select,DatePicker,Cascader等組件選項框隨頁面滾動的問題解決


一、場景

  在開發過程中,會使用很多的Select、DatePicker等組件,當這些組件在可滾動的區域內滾動時,你會發現該組件的選項框也會跟着滾動,產生分離。如下圖所示。

 

二、解決方法

  通過查詢相應的官方API,發現官方給我們提供了getPopupContainer屬性,該屬性是菜單渲染的父節點,默認是body。只要添加該屬性,設置好父節點,就可以解決這種分離。

  添加getPopupContainer屬性

getPopupContainer={(triggerNode: any) => triggerNode.parentNode}
   triggerNode:當前元素的節點
   triggerNode.parentNode:最近的父級元素節點

  在Select、DatePicker、Cascader添加getPopupContainer屬性栗子:

    <div style={{ margin: 10, overflow: 'scroll', height: 500 }}>
        <div style={{ padding: 100, height: 1000 }} id='getPopupContainerDiv'>
          <Select
            defaultValue="1"
            style={{ width: 120 }}
            getPopupContainer={(triggerNode: any) => triggerNode.parentNode}
          >
            <Option value="1">選項1</Option>
            <Option value="2">選項2</Option>
          </Select>

          <DatePicker
            getPopupContainer={(triggerNode: any) => triggerNode.parentNode}
            style={{ width: '160px' }}
            format="YYYY-MM-DD"
          />

          <Cascader
            getPopupContainer={(triggerNode: any) => triggerNode.parentNode}
            options={options}
          />
        </div>
      </div>

  設置完成之后,發現Select是沒有分離的,但是DatePicker和Cascader還是會分離。

     這是為什么呢?首先看了一下版本,我的antd版本是4.x的,在3.x是正常的,這就讓人掉頭發了。

  沒辦法,先硬着頭皮打印一下這三個組件的triggerNode以及triggerNode.parentNode觀察一下。

  Select的triggerNode以及triggerNode.parentNode

  

   DatePicker和Cascader的triggerNode以及triggerNode.parentNode

  

   果真,三個組件的triggerNode.parentNode有差異,DatePicker和Cascader直接找到了最外層的div,他的節點還是在最外層,導致分離。

  原因找到了,如何解決呢?

  既然官方提供的是定位到父節點,就可以解決分離問題,那么我直接定位到本身節點,那豈不是也可以解決?將getPopupContainer代碼修改一番,如下:

getPopupContainer={(triggerNode: any) => triggerNode}

  結果:修改完之后運行,發現都不再分離

三、全局設置getPopupContainer

  一般來說,項目中會用到很多這種選擇組件,我們如果一個一個的去添加getPopupContainer屬性,那么久太麻煩了,這就需要我們全局配置。

   <ConfigProvider
      locale={zh_CN}
      getPopupContainer={(node: any) => node}          //ant 4.x
      // getPopupContainer={(triggerNode: any) => triggerNode.parentNode} //ant 3.x
      <Route />
    </ConfigProvider >

  這樣配置完成之后,全局就配置完畢,不需要我們每個都去添加。

四、全局配置后,在Modal中使用報錯解決

  開發項目,肯定會使用Modal彈框組件,在Modal組件中也避免不了使用選擇組件,在全局配置完getPopupContainer后,發現Modal會報錯。

  ant3.x版本報錯,4.x版本直接空白

  

   官方API給的解釋是:全局設置getPopupContainer 觸發節點時,Modal 的用法不存在 triggerNode導致報錯

  解決方法:增加一個判斷條件

 <ConfigProvider
      locale={zh_CN}
      //getPopupContainer={(node: any) => node}
      getPopupContainer={(node: any) => {
        if (node) {
          return node             //ant 4.x
          // return node.parentNode;    //ant 3.x
        }   return document.body;
      }}
    >
      <Route />
    </ConfigProvider >

五、完整代碼

import React from 'react';
import { Button, Select, DatePicker, Cascader, Modal, Form } from 'antd'
const Option = Select.Option
export default () => {
  const [form] = Form.useForm();
  const options = [
    {
      value: 'zhejiang',
      label: 'Zhejiang',
      children: [
        {
          value: 'hangzhou',
          label: 'Hangzhou',
          children: [
            {
              value: 'xihu',
              label: 'West Lake',
            },
          ],
        },
      ],
    },
    {
      value: 'jiangsu',
      label: 'Jiangsu',
      children: [
        {
          value: 'nanjing',
          label: 'Nanjing',
          children: [
            {
              value: 'zhonghuamen',
              label: 'Zhong Hua Men',
            },
          ],
        },
      ],
    },
  ];
  const triggerNodeFunc = (triggerNode: any) => {
    console.log(triggerNode)
    console.log(triggerNode.parentNode)
    return triggerNode
  }
  return (
    <div>
      <Modal
        title='組件選項框滾動分離'
        visible={true}
        bodyStyle={
          {
            maxHeight: '300px',
            overflowY: 'auto'
          }
        }
      >
        <div style={{ padding: 100, height: 1000 }}>
          <Select
            defaultValue="1"
            style={{ width: 120 }}
          >
            <Option value="1">選項1</Option>
            <Option value="2">選項2</Option>
          </Select>

          <DatePicker
            style={{ width: '160px' }}
            format="YYYY-MM-DD"
          />

          <Cascader
            options={options}
          />
        </div>
      </Modal>
      {/* <div style={{ margin: 10, overflow: 'scroll', height: 500 }}>
        <div style={{ padding: 100, height: 1000 }} id='getPopupContainerDiv'>
          <Select
            defaultValue="1"
            style={{ width: 120 }}
          // getPopupContainer={(triggerNode: any) => triggerNodeFunc(triggerNode)}
          >
            <Option value="1">選項1</Option>
            <Option value="2">選項2</Option>
          </Select>

          <DatePicker
            // getPopupContainer={(triggerNode: any) => triggerNode}
            style={{ width: '160px' }}
            format="YYYY-MM-DD"
          />

          <Cascader
            // getPopupContainer={(triggerNode: any) => triggerNodeFunc(triggerNode)}
            options={options}
          />
        </div>
      </div> */}
    </div >
  );
}
滾動樣式代碼
ReactDOM.render(
  <Provider store={store}>
    <ConfigProvider
      locale={zh_CN}
      // getPopupContainer={(node: any) => node}
      // getPopupContainer={(triggerNode: any) => triggerNode.parentNode}
      getPopupContainer={(node: any) => {
        if (node) {
          return node
          // return node.parentNode;
        }
        return document.body;
      }}
    >
      <Route />
    </ConfigProvider >
  </Provider>,
  document.getElementById('root')
);
全局配置代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM