PopMenu 气泡菜单

import {
  TaButton,
  TaCell,
  TaGroup,
  TaPopMenu,
  PlacementType,
  PopupOnCancel,
  PopupOnVisibleStateChange,
  showPopMenu,
  showToast,
  showDialog,
  PopMenuOnConfirm
} from '@/index'
import { useRef, useState } from 'react'

interface showArgs {
  selector?: string
  placement?: PlacementType
  visibleEvent?: boolean
  confirmEvent?: boolean
}

const options = [
  {
    icon: 'HeartOutlined',
    name: '爱心'
  },
  {
    icon: 'StarOutlined',
    name: '星星'
  },
  {
    icon: 'CircleOutlined',
    name: '圈圈',
    disabled: true
  }
]

export default function ExpPopMenu() {
  const [selector, setSelector] = useState<string>()
  const [placement, setPlacement] = useState<PlacementType>()

  const [visible, setVisible] = useState(false)
  const [visible2, setVisible2] = useState(false)

  const confirmEvent = useRef(false)
  const visibleEvent = useRef(false)

  function onShow(args: showArgs = {}) {
    setSelector(args.selector)
    setPlacement(args.placement)

    visibleEvent.current = !!args.visibleEvent
    confirmEvent.current = !!args.confirmEvent

    visibleEvent.current = !!args.visibleEvent

    setVisible(true)
  }

  const onVisibleStateChange: PopupOnVisibleStateChange = ({ state }) => {
    if (visibleEvent.current) {
      console.log('onVisibleStateChange', state)
      showToast(`${state} 事件触发`)
    }
    if (state === 'hidden') {
      visibleEvent.current = false
      confirmEvent.current = false
    }
  }

  const onConfirm: PopMenuOnConfirm = res => {
    if (confirmEvent.current) {
      console.log('confirm')
      showDialog({
        title: '选择了',
        showCancel: false,
        content: `item.name: '${res.item.name}'\nindex: ${res.index}`
      })
    }
  }

  const onCancel: PopupOnCancel = res => {
    if (confirmEvent.current) {
      console.log('cancel', res)
      showToast('取消了')
    }
  }

  function onCallApi(selector: string) {
    showPopMenu({
      selector,
      options: options,
      placement: 'top',
      success: res => {
        console.log('success', res)
        if (res.confirm) {
          showToast(`选择了 ${res.detail.item.name}`)
        } else {
          showToast('取消了')
        }
      }
    })
  }

  return (
    <>
      <TaGroup title="基础用法">
        <TaCell label="基础">
          <TaButton
            size="small"
            id="popMenu"
            shape="circle"
            icon="MenuOutlined"
            onClick={() => onShow({ selector: '#popMenu' })}
          ></TaButton>
        </TaCell>
        <TaCell label="不展示蒙层">
          <TaButton
            size="small"
            id="popMenuNoMask"
            shape="circle"
            icon="MenuOutlined"
            onClick={() => setVisible2(true)}
          ></TaButton>
        </TaCell>
      </TaGroup>
      <TaGroup title="方向 placement=top/bottom/left/right">
        <div className="exp-popover-box2">
          <div>
            <TaButton
              size="small"
              id="popMenuTop2"
              shape="circle"
              icon="UpOutlined"
              onClick={() =>
                onShow({ placement: 'top', selector: '#popMenuTop2' })
              }
            ></TaButton>
          </div>
          <div>
            <TaButton
              size="small"
              id="popMenuLeft2"
              shape="circle"
              icon="LeftOutlined"
              onClick={() =>
                onShow({ placement: 'left', selector: '#popMenuLeft2' })
              }
            ></TaButton>
            <TaButton
              className="exp-popover-box2-ml"
              size="small"
              id="popMenuRight2"
              shape="circle"
              icon="RightOutlined"
              onClick={() =>
                onShow({ placement: 'right', selector: '#popMenuRight2' })
              }
            ></TaButton>
          </div>
          <div>
            <TaButton
              size="small"
              id="popMenuBottom2"
              shape="circle"
              icon="DownOutlined"
              onClick={() =>
                onShow({ placement: 'bottom', selector: '#popMenuBottom2' })
              }
            ></TaButton>
          </div>
        </div>
      </TaGroup>
      <TaGroup title="事件监听">
        <TaCell label="confirm/cancel">
          <TaButton
            size="small"
            id="popMenuEvent"
            shape="circle"
            icon="MenuOutlined"
            onClick={() =>
              onShow({ confirmEvent: true, selector: '#popMenuEvent' })
            }
          ></TaButton>
        </TaCell>
        <TaCell label="onVisibleStateChange">
          <TaButton
            size="small"
            id="popMenuEvent2"
            shape="circle"
            icon="MenuOutlined"
            onClick={() =>
              onShow({ visibleEvent: true, selector: '#popMenuEvent2' })
            }
          ></TaButton>
        </TaCell>
      </TaGroup>
      <TaGroup title="API">
        <TaCell label="showPopMenu">
          <TaButton
            size="small"
            id="popMenuApi"
            shape="circle"
            icon="MenuOutlined"
            onClick={() => onCallApi('#popMenuApi')}
          ></TaButton>
        </TaCell>
      </TaGroup>
      <TaPopMenu
        options={options}
        placement={placement}
        selector={selector}
        visible={visible}
        onUpdateVisible={v => setVisible(v)}
        onVisibleStateChange={onVisibleStateChange}
        onCancel={onCancel}
        onConfirm={onConfirm}
      />
      <TaPopMenu
        options={options}
        visible={visible2}
        selector="#popMenuNoMask"
        showMask={false}
        content="无蒙层气泡内容"
        onUpdateVisible={v => setVisible2(v)}
      />
    </>
  )
}

Import

import { TaPopMenu } from 'tantalum-ui-mobile-react'

具体的引入方式可以参考引入组件

Import Type

组件导出的类型定义:

import type {
  PopMenuOption,
  PopMenuOnConfirm,
  VisibleState,
  PopupOnVisibleStateChange,
  PopupOnCancel
} from 'tantalum-ui-mobile-react'

Props

属性类型默认值必填说明
visiblebooleanfalse是否显示
selectorstring | HTMLElement从哪个元素展开,如果是 string,则为可以被 document.querySelector(selector) 获取到
placementPlacementType'bottom'展开位置,可选 'bottom', 'top', 'left', 'right'
showMaskbooleantrue是否展示蒙层,如果设置不展示,气泡则是跟随 selector 对应的元素
optionsPopMenuOption[]选项列表

PopMenuOption 的结构

interface MenuOption {
  name: string
  icon?: IconData
  disabled?: boolean
}
key类型默认值必填说明
namestring选项名
disabledstringfalse是否禁用
iconstring图标,使用 Icon 组件
const options = [
  {
    name: '选项1',
    disabled: false,
    icon: 'MenuOutlined'
  }
]

Events

事件描述回调函数参数TypeScript 函数
onConfirm确认按钮点击时触发payload: { item: { name: string }, index: number }PopMenuOnConfirm
onCancel取消时触发payload: { source: string }PopupOnCancel
onVisibleStateChange展示隐藏时触发payload: { state: VisibleState }PopupOnVisibleStateChange
onUpdateVisible展示隐藏时触发visible: boolean 是否显示

VisibleState 值说明

说明备注
show展示时触发
shown展示且动画结束后触发
hide隐藏时触发可能携带其他参数 cancel, maskClick, closeClick 等
hidden隐藏且动画结束后触发可能携带其他参数 cancel, maskClick, closeClick 等

showPopMenu(object)

显示气泡菜单。

object

属性类型默认值必填说明
selectorstring | HTMLElement从哪个元素展开,如果是 string,则为可以被 document.querySelector(selector) 获取到
placementPlacementType'bottom'展开位置,可选 'bottom', 'top', 'left', 'right'
optionsPopMenuOption[]选项列表
success(payload: SuccessPayload) => void接口调用成功(在用户做出选择后,如取消,选择选项)的回调函数
fail(e: Error) => void接口调用失败(如传入错误的参数)的回调函数(不传入 fail 遇错误直接抛出)
complete() => void弹窗关闭或调用失败的回调函数

SuccessPayload

属性类型说明
confirm?boolean为 true 时,表示用户点击了选项,此时返回 detail
cancel?boolean为 true 时,表示用户点击了取消
detail?.item.namestringconfirm=true 时点击 item 的选项名
detail?.indexnumberconfirm=true 时点击 item 的索引

Usage

具体调用方式可以参考API 调用

showPopMenu({
  selector: '#popMenuTarget',
  options: [
    {
      icon: 'HeartOutlined',
      name: '爱心'
    },
    {
      icon: 'StarOutlined',
      name: '星星'
    },
    {
      icon: 'CircleOutlined',
      name: '圈圈',
      disabled: true
    }
  ],
  placement: 'top',
  success: res => {
    console.log('select', res)
  }
})