处理“长按”以在 Ant Design 中显示下拉菜单

问题描述 投票:0回答:1

此组件通过触发

context menu
事件在桌面设备上显示下拉菜单。是否可以在触摸设备上使用此下拉组件,但不使用
context menu
事件,而是使用
long press
显示下拉列表?触摸设备上没有
context menu
事件。

我想用

long press
技术显示下拉菜单。

import React from 'react';
import type { MenuProps } from 'antd';
import { Dropdown, theme } from 'antd';

const items: MenuProps['items'] = [
  {
    label: '1st menu item',
    key: '1',
  },
  {
    label: '2nd menu item',
    key: '2',
  },
  {
    label: '3rd menu item',
    key: '3',
  },
];

const App: React.FC = () => {
  const {
    token: { colorBgLayout, colorTextTertiary },
  } = theme.useToken();

  return (
    <Dropdown menu={{ items }} trigger={['contextMenu']}>
      <div
        style={{
          color: colorTextTertiary,
          background: colorBgLayout,
          height: 200,
          textAlign: 'center',
          lineHeight: '200px',
        }}
      >
        Right Click on here
      </div>
    </Dropdown>
  );
};

export default App;

我尝试用额外的 div 包裹内容并在其上应用触摸事件。这是正确的方法还是可能有一些内置的解决方案?

      <div
        onTouchStart={handleTouchStart}
        onTouchEnd={handleTouchEnd}
        onContextMenu={e => e.preventDefault()}
      >
        Right Click on here or Long Press on Touch Devices
      </div>
reactjs antd
1个回答
0
投票

当触发器设置为

contextMenu

时,下拉菜单将 4 个道具传递给它的子级
  1. 类名
  2. 已禁用
  3. onClick(禁用时不可用)
  4. onContextMenu(当禁用为 true 时不可用)

我尝试使用pointerDown和pointerUp事件而不是onTouchEvent(antd抛出错误。可能是onTouchEvent中缺少某些字段/值)。您可以使用指针向下和向上事件来检测长按并调用 onContextMenu 函数来打开上下文菜单。

完整代码如下:

import type { MenuProps } from 'antd';
import { Dropdown, theme } from 'antd';
import type React from 'react';
import { type ForwardedRef, forwardRef, useRef } from 'react';

const items: MenuProps['items'] = [
    {
        label: '1st menu item',
        key: '1'
    },
    {
        label: '2nd menu item',
        key: '2'
    },
    {
        label: '3rd menu item',
        key: '3'
    }
];

const App: React.FC = () => {
    return (
        <Dropdown menu={{ items }} trigger={['contextMenu']}>
            <Content />
        </Dropdown>
    );
};

export default App;

interface ContentProps {
    onClick?: () => void;
    onContextMenu?: (e: React.MouseEvent) => void;
    className?: string;
    // if disabled is true, onContextMenu and onClick events are not available
    disabled?: boolean;
}

const Content = forwardRef((props: ContentProps, ref: ForwardedRef<HTMLDivElement>) => {
    const { onContextMenu, className, disabled } = props;

    const {
        token: { colorBgLayout, colorTextTertiary }
    } = theme.useToken();
    const timer = useRef<ReturnType<typeof setTimeout>>(null);

    const clearTimer = () => {
        if (timer.current) {
            clearTimeout(timer.current);
            timer.current = null;
        }
    };

    return (
        <div
            ref={ref}
            style={{
                color: colorTextTertiary,
                background: colorBgLayout,
                height: 200,
                textAlign: 'center',
                lineHeight: '200px'
            }}
            className={className}
            onContextMenu={onContextMenu}
            onPointerDown={(e) => {
                if (disabled || e.pointerType !== 'touch') {
                    return;
                }

                // Clear timer if it is already running
                clearTimer();

                timer.current = setTimeout(() => {
                    onContextMenu?.(e);
                    clearTimer();
                }, 2000);
            }}
            onPointerUp={clearTimer}
        >
            Right Click on here or Long Press on Touch Devices
        </div>
    );
});
© www.soinside.com 2019 - 2024. All rights reserved.