# Trigger 触发器

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/trigger/freepass)
- 平台：PC
- 维护者：蒋贝贝
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[Trigger]

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import React, { Component } from 'react';
import { Trigger, Input, Button, constants, Select, Dialog, Popover } from '@weapp/ui';
import { eventEmitter } from '@weapp/utils';

const data = [
  { id: 'left', content: 'left' },
  { id: 'right', content: 'right' },
  { id: 'top', content: 'top' },
  { id: 'bottom', content: 'bottom' },
  { id: 'topLeft', content: 'topLeft' },
  { id: 'topRight', content: 'topRight' },
  { id: 'bottomRight', content: 'bottomRight' },
  { id: 'bottomLeft', content: 'bottomLeft' },
  { id: 'leftTop', content: 'leftTop' },
  { id: 'rightTop', content: 'rightTop' },
  { id: 'leftBottom', content: 'leftBottom' },
  { id: 'rightBottom', content: 'rightBottom' },
  { id: 'middle', content: 'middle' },
]

const { uiAppName } = constants;
const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
  count?: number;
  position?: any;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  componentDidMount() {
    eventEmitter.addListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  componentWillUnmount() {
    eventEmitter.removeListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  onVisibleChange = (customEventOptions: any) => {
    if (customEventOptions && customEventOptions.detail) {
      console.log(customEventOptions.detail.visible)
    }
  }
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
      count: 0,
      position: 'bottomLeft',
    }
  }
  onBtnClick = () => this.setState({
    count: (this.state.count || 0) + 1,
  })
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  onChange = (position: any) => this.setState({ position });

  render() {
    const { count = 0, popupVisible, position } = this.state;
    return (
      <div className={prefixCls}>
        弹层位置：
        <Select
          data={data}
          value={position}
          onChange={this.onChange}
        />
        <div className={`${prefixCls}-trigger`}>
          <Popover placement={position} visible={popupVisible} popup={<div className="test01">111111</div>}>
            <Trigger
              popupId="1"
              popup={(
                <div className="dropDown_animation" style={{ background: '#66B6F3', color: '#fff', padding: '100px 200px' }}>
                  {count} -
                  <Button onClick={this.onBtnClick}>
                    Add
                  </Button>
                </div>
              )}
              popupPlacement={position}
              popupClassName="popupClassName"
              popupVisible={popupVisible}
              onPopupVisibleChange={this.onPopupVisibleChange}
              // needAnimateHeight={true}
              // animateHeightProps={{
              //   duration: 120,
              // }}
              enableEventEmitter
            >
              <Input />
            </Trigger>
          </Popover>
        </div >
      </div >
    );
  }
}

export default TriggerDemo;
```

### 指定渲染父节点

默认渲染到 body 上，如遇滚动定位问题，试试修改为滚动的区域，并相对其定位

```jsx
import { Component } from 'react';
import { Trigger, Input, Button, constants, Select } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
  count?: number;
  position?: any;
  maskValue?: string;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
      count: 0,
      position: 'left',
      maskValue: 'close',
    }
  }
  onBtnClick = () => this.setState({ count: (this.state.count || 0) + 1 })
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  getPopupContainer = () => this.childRef;
  onChange = (position: any) => this.setState({ position });
  onChangeMaskValue = (maskValue: any) => this.setState({ maskValue });
  render() {
    const { count = 0, popupVisible, position, maskValue } = this.state;
    const data = [
      { id: 'left', content: 'left' },
      { id: 'right', content: 'right' },
      { id: 'top', content: 'top' },
      { id: 'bottom', content: 'bottom' },
      { id: 'topLeft', content: 'topLeft' },
      { id: 'topRight', content: 'topRight' },
      { id: 'bottomRight', content: 'bottomRight' },
      { id: 'bottomLeft', content: 'bottomLeft' },
      { id: 'leftTop', content: 'leftTop' },
      { id: 'rightTop', content: 'rightTop' },
      { id: 'leftBottom', content: 'leftBottom' },
      { id: 'rightBottom', content: 'rightBottom' },
    ]
    const dataMask = [
      { id: 'close', content: '关闭蒙层' },
      { id: 'open', content: '打开蒙层' },
    ]
    return (
      <div className={prefixCls}>
        弹层位置：
        <Select
          data={data}
          value={position}
          onChange={this.onChange}
        />
        <br />
        <br />
        蒙层设置：
        <Select
          data={dataMask}
          value={maskValue}
          onChange={this.onChangeMaskValue}
        />
        <div className={`${prefixCls}-trigger`} style={{ border: '1px solid red', marginLeft: 100, marginRight: 100 }}>
          <Trigger
            action={['click']}
            popup={(
              <div style={{ background: '#66B6F3', color: '#fff', padding: '10px 20px', minHeight: 66, minWidth: 95 }}>
                {count} -
                <Button onClick={this.onBtnClick}>
                  Add
                </Button>
              </div>
            )}
            popupPlacement={position}
            popupClassName="popupClassName"
            popupVisible={popupVisible}
            onPopupVisibleChange={this.onPopupVisibleChange}
            getPopupContainer={this.getPopupContainer}
            mask={maskValue === 'open'}
            maskClosable={maskValue === 'open'}
          >
            <div ref={this.getChildRef}>
              <Input />
            </div>
          </Trigger>
        </div>
      </div>
    );
  }
}

export default TriggerDemo;
```

### 覆盖内容定位

覆盖内容定位

```jsx
import { Component } from 'react';
import { Trigger, constants, Icon, utils } from '@weapp/ui';
import { classnames } from '@weapp/utils';

const { needRTL } = utils;
const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
    }
  }
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  getPopupContainer = () => this.childRef;
  hidePopop = () => {
    this.onPopupVisibleChange(false);
  }
  showPopop = () => {
    this.onPopupVisibleChange(true);
  }
  render() {
    const { popupVisible } = this.state;
    const containerCls = classnames(`${prefixCls}-cover-container`, {
      "needRTL": needRTL?.(),
    })
    return (
      <div className={prefixCls}>
        <div className={`${prefixCls}-trigger`}>
          <Trigger
            popup={(
              <div className={containerCls}>
                <div className={`${prefixCls}-cover-children`} onMouseLeave={this.hidePopop} onMouseEnter={this.showPopop}>
                  <Icon name={'Icon-task-o'} />
                </div>
                <div className={`${prefixCls}-cover-content`} onMouseLeave={this.hidePopop} onMouseEnter={this.showPopop}>
                  <div>1</div>
                  <div>2</div>
                  <div>3</div>
                </div>
              </div>
            )}
            popupClassName="popupClassName"
            popupPlacement={needRTL?.() ? 'bottomRight' : 'bottomLeft'}
            popupVisible={popupVisible}
            onPopupVisibleChange={this.onPopupVisibleChange}
            getPopupContainer={this.getPopupContainer}
            cover
            action="hover"
            closeAnimation
          >
            <div ref={this.getChildRef} className={`${prefixCls}-cover`}>
              <Icon name={'Icon-task-o'} />
            </div>
          </Trigger>
        </div>
      </div>
    );
  }
}

export default TriggerDemo;
```

### 覆盖内容定位(点击触发)

覆盖内容定位(点击触发)

```jsx
import { Component, MouseEvent } from 'react';
import { Trigger, constants, Icon, utils } from '@weapp/ui';
import { classnames } from '@weapp/utils';
const { needRTL } = utils;

const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  containerRef?: HTMLDivElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
    }
  }
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  getPopupContainer = () => this.childRef;
  setContainerRef = (el: HTMLDivElement) => this.containerRef = el;
  hidePopop = (e: MouseEvent) => {
    if (e.target === this.containerRef) {
      this.onPopupVisibleChange(false);
    }
  }
  render() {
    const { popupVisible } = this.state;
    const containerCls = classnames(`${prefixCls}-cover-container`, {
      "needRTL": needRTL?.(),
    })
    return (
      <div className={prefixCls}>
        <div className={`${prefixCls}-trigger`}>
          <Trigger
            popup={(
              <div className={containerCls} ref={this.setContainerRef} onClick={this.hidePopop}>
                <div className={`${prefixCls}-cover-children`}>
                  <Icon name={'Icon-task-o'} />
                </div>
                <div className={`${prefixCls}-cover-content`}>
                  <div>1</div>
                  <div>2</div>
                  <div>3</div>
                </div>
              </div>
            )}
            popupClassName="popupClassName"
            popupPlacement={needRTL?.() ? 'leftTop' : 'rightTop'}
            popupVisible={popupVisible}
            onPopupVisibleChange={this.onPopupVisibleChange}
            // getPopupContainer={this.getPopupContainer}
            cover
            action="click"
            closeAnimation
          >
            <div ref={this.getChildRef} className={`${prefixCls}-cover`}>
              <Icon name={'Icon-task-o'} />
            </div>
          </Trigger>
        </div>
      </div>
    );
  }
}

export default TriggerDemo;
```

### 多级弹层嵌套

多级弹层嵌套

```jsx
import { Component } from 'react';
import { Trigger, Input, constants, Help } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
    }
  }
  getPopupContainer = () => this.childRef;
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  render() {
    const { popupVisible } = this.state;
    return (
      <div className={prefixCls}>
        弹层位置：
        <div className={`${prefixCls}-trigger`}>
          <Trigger
            action={'click'}
            blacklist={['div[id="ui-demo-trigger-popup-container"]']}
            popup={(
              <div className={`${prefixCls}-popup`}>
                <Trigger
                  getPopupContainer={this.getPopupContainer} action={['click']}
                  popup={(<div className={`${prefixCls}-popup-sub`}>
                    <Help title="二级弹出层内容" />
                  </div>)}
                >
                  <div ref={this.getChildRef} id="ui-demo-trigger-popup-container">
                    <Input />
                  </div>
                </Trigger>
              </div>
            )}
            popupClassName="popupClassName"
            popupVisible={popupVisible}
            onPopupVisibleChange={this.onPopupVisibleChange}
          >
            <Input />
          </Trigger>
        </div>
      </div>
    );
  }
}

export default TriggerDemo;
```

### 滚动时跟随

滚动时跟随

```jsx
import { Component } from 'react';
import { Trigger, Input, Button, constants, Select } from '@weapp/ui';
import { eventEmitter } from '@weapp/utils';

const { uiAppName } = constants;
const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps{
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
  count?: number;
  position?: any;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  componentDidMount() {
    eventEmitter.addListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  componentWillUnmount() {
    eventEmitter.removeListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  onVisibleChange = (customEventOptions: any) => {
    if (customEventOptions && customEventOptions.detail) {
      console.log(customEventOptions.detail.visible)
    }
  }
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
      count: 0,
      position: 'bottomLeft',
    }
  }
  onBtnClick = () => this.setState({ count: (this.state.count || 0) + 1 })
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  onChange = (position: any) => this.setState({ position });
  render() {
    const { count = 0, popupVisible, position } = this.state;
    const data = [
      {id: 'left', content: 'left'},
      {id: 'right', content: 'right'},
      {id: 'top', content: 'top'},
      {id: 'bottom', content: 'bottom'},
      {id: 'topLeft', content: 'topLeft'},
      {id: 'topRight', content: 'topRight'},
      {id: 'bottomRight', content: 'bottomRight'},
      {id: 'bottomLeft', content: 'bottomLeft'},
      {id: 'leftTop', content: 'leftTop'},
      {id: 'rightTop', content: 'rightTop'},
      {id: 'leftBottom', content: 'leftBottom'},
      {id: 'rightBottom', content: 'rightBottom'},
    ]
    return (
      <div className={prefixCls}>
        弹层位置：
        <Select
          data={data}
          value={position}
          onChange={this.onChange}
        />
        <div className={`${prefixCls}-trigger`}>
          <Trigger
            action={['click']}
            popupId="1"
            popup={(
              <div className="dropDown_animation" style={{ background: '#66B6F3', color: '#fff', padding: '100px 200px' }}>
                {count} - 
                <Button onClick={this.onBtnClick}>
                  Add
                </Button>
              </div>
            )}
            popupPlacement={position}
            popupClassName="popupClassName" 
            popupVisible={popupVisible}
            onPopupVisibleChange={this.onPopupVisibleChange}
            // needAnimateHeight={true}
            // animateHeightProps={{
            //   duration: 120,
            // }}
            enableEventEmitter
            followScroll
            // enableWheelEventEmitter
          >
            <Input />
          </Trigger>
        </div>
      </div>
    );
  }
}

export default TriggerDemo;
```

### 黑名单

黑名单处理在popup中渲染dialog弹窗，在鼠标移入时意外打开的事件

```jsx
import React, { Component } from 'react';
import { Trigger, Input, Button, constants, Dialog, utils } from '@weapp/ui';
import { eventEmitter } from '@weapp/utils';

const { needRTL } = utils;
const { uiAppName } = constants;
const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
  forceRender?: boolean;
}
interface TriggerDemoState {
  popupVisible?: boolean;
  popupVisible2?: boolean
  position?: any;
  dialogVisible?: boolean
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  componentDidMount() {
    eventEmitter.addListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  componentWillUnmount() {
    eventEmitter.removeListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  onVisibleChange = (customEventOptions: any) => {
    if (customEventOptions && customEventOptions.detail) {
      console.log(customEventOptions.detail.visible)
    }
  }
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
      position: needRTL?.() ? 'bottomRight' : 'bottomLeft',
      dialogVisible: false
    }
  }
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  onPopupVisibleChange2 = (visible?: boolean) => this.setState({ popupVisible2: visible })

  onMouseEnter = (e: React.MouseEvent) => {
    console.log('onMouseEnter', e)
    e.stopPropagation()
    e.preventDefault()
  }
  onDialogOpen = () => {
    this.setState({ dialogVisible: true })
  }
  onDialogClose = () => {
    this.setState({ dialogVisible: false })
  }
  render() {
    const { popupVisible, popupVisible2, position } = this.state;
    return (
      <div className={prefixCls}>
        <h4>未配置黑名单：当鼠标滑入测滑框时会意外打开trigger弹窗</h4>
        <Trigger
          // action={['click']}
          popupId="1"
          popup={(
            <div className="dropDown_animation" style={{ background: '#66B6F3', color: '#fff', padding: '100px 200px' }}>
              <Button onClick={this.onDialogOpen}>
                打开测滑框
              </Button>
              <Button onClick={this.onDialogClose}>
                关闭测滑框
              </Button>
              <Dialog
                visible={this.state.dialogVisible}
                placement={'right'}
                dialogId={'test_dialog'}
                onClose={this.onDialogClose}
                maskClosable
              >
                <div style={{ border: '1px solid blue' }} onMouseEnter={this.onMouseEnter}>
                  测试测试
                </div>
              </Dialog>
            </div>
          )}
          popupPlacement={position}
          popupClassName="popupClassName"
          popupVisible={popupVisible}
          onPopupVisibleChange={this.onPopupVisibleChange}
          enableEventEmitter
        >
          <Input style={{ width: 200 }} />
        </Trigger>
        <h4>配置了黑名单：当鼠标移入测滑框时不会影响trigger弹窗</h4>
        <Trigger
          // action={['click']}
          popupId="1"
          popup={(
            <div className="dropDown_animation" style={{ background: '#66B6F3', color: '#fff', padding: '100px 200px' }}>
              <Button onClick={this.onDialogOpen}>
                打开测滑框
              </Button>
              <Button onClick={this.onDialogClose}>
                关闭测滑框
              </Button>
              <Dialog
                visible={this.state.dialogVisible}
                placement={'right'}
                dialogId={'test_dialog'}
                onClose={this.onDialogClose}
                maskClosable
              >
                <div style={{ border: '1px solid blue' }} onMouseEnter={this.onMouseEnter}>
                  测试测试
                </div>
              </Dialog>
            </div>
          )}
          popupPlacement={position}
          popupClassName="popupClassName"
          popupVisible={popupVisible2}
          onPopupVisibleChange={this.onPopupVisibleChange2}
          enableEventEmitter
          childrenHoverBlacklist={
            [`div[id="test_dialog"]`]
          }
        >
          <Input style={{ width: 200 }} />
        </Trigger>
      </div>
    );
  }
}

export default TriggerDemo;
```

### 小屏幕处理

对于trigger组件较大面板而屏幕较小的情况，会居中展示

```jsx
import React, { Component } from 'react';
import { Trigger, Input, constants, Select, Popover } from '@weapp/ui';
import { eventEmitter } from '@weapp/utils';

const data = [
  { id: 'left', content: 'left' },
  { id: 'right', content: 'right' },
  { id: 'top', content: 'top' },
  { id: 'bottom', content: 'bottom' },
  { id: 'topLeft', content: 'topLeft' },
  { id: 'topRight', content: 'topRight' },
  { id: 'bottomRight', content: 'bottomRight' },
  { id: 'bottomLeft', content: 'bottomLeft' },
  { id: 'leftTop', content: 'leftTop' },
  { id: 'rightTop', content: 'rightTop' },
  { id: 'leftBottom', content: 'leftBottom' },
  { id: 'rightBottom', content: 'rightBottom' },
  { id: 'middle', content: 'middle' },
]

const { uiAppName } = constants;
const prefixCls = `${constants.uiPcClsPrefix}-demo-trigger`;
interface TriggerDemoProps {
  popupVisible?: boolean;
  popupPlacement?: any;
}
interface TriggerDemoState {
  popupVisible?: boolean;
  position?: any;
}

class TriggerDemo extends Component<TriggerDemoProps, TriggerDemoState> {
  componentDidMount() {
    eventEmitter.addListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  componentWillUnmount() {
    eventEmitter.removeListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  }
  onVisibleChange = (customEventOptions: any) => {
    if (customEventOptions && customEventOptions.detail) {
      console.log(customEventOptions.detail.visible)
    }
  }
  getChildRef = (el: HTMLDivElement) => this.childRef = el;
  childRef?: HTMLElement;
  constructor(props: TriggerDemoProps) {
    super(props);
    this.state = {
      popupVisible: false,
      position: 'bottomLeft',
    }
  }
  onPopupVisibleChange = (visible?: boolean) => this.setState({ popupVisible: visible })
  onChange = (position: any) => this.setState({ position });

  render() {
    const { popupVisible, position } = this.state;
    return (
      <div className={prefixCls}>
        弹层位置：
        <Select
          data={data}
          value={position}
          onChange={this.onChange}
        />
        <Trigger
          popupId="1"
          popup={(
            <div style={{ width: 800, height: 600, background: '#66B6F3', color: '#fff', padding: '100px 200px' }}>
            </div>
          )}
          popupPlacement={position}
          popupClassName="popupClassName"
          popupVisible={popupVisible}
          onPopupVisibleChange={this.onPopupVisibleChange}
          // needAnimateHeight={true}
          // animateHeightProps={{
          //   duration: 120,
          // }}
          enableEventEmitter
          useFixedMiddlePopupPlacement
        >
          <Input />
        </Trigger>
      </div>
    );
  }
}

export default TriggerDemo;
```

## API

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |  |
| --- | --- | --- | --- | --- | --- |
| popup | 弹层内容 | ReactNode \| (() => ReactNode) |  |  |  |
| popupVisible | 弹层显示/隐藏 | boolean |  |  |  |
| defaultPopupVisible | 弹层默认显示/隐藏 | boolean |  |  |  |
| onPopupVisibleChange | 弹层默认显示/隐藏事件 | (visible: boolean) => void |  |  |  |
| action | 弹层动作(可设置 hover/click) | string \| string[] |  | `hover` |  |
| popupClassName | 弹层自定义 class | string |  |  |  |
| popupId | 弹层自定义id | string |  |  |  |
| popupStyle | 弹层自定义样式 | CSSProperties |  |  |  |
| mask | 是否展示遮罩 | boolean | 否 |  |  |
| maskClosable | 点击蒙层是否允许关闭 | boolean | 否 |  |  |
| maskStyle | 蒙层自定义样式 | CSSProperties | 否 |  |  |
| zIndex | 弹层容器层级 | number | 否 |  |  |
| popupPlacement | 弹层位置 | PopupPlacement | 否 |  |  |
| popupTransitionName | 弹层动画效果,可设置`slide-up`，`slide-down`，`slide-left`，`slide-right` | string | 否 |  |  |
| forceRender | 预渲染 | boolean | 否 |  |  |
| closeAnimation | 关闭动画效果 | boolean | 否 |  |  |
| getPopupContainer | 指定渲染父节点, 默认渲染到 body 上，如遇滚动定位问题，试试修改为滚动的区域，并相对其定位 | () => (HTMLElement \| undefined) | 否 |  |  |
| cover | 覆盖内容定位(仅 top/topLeft/topRight/bottom/bottomLeft/bottomRight 定位支持) | boolean | 否 |  |  |
| needAnimateHeight | 开启弹层高度动画效果 | boolean | 否 |  |  |
| animateHeightProps | 动画效果设置(继承 AnimateHeight 组件参数) | IAnimateHeightBaseProps | 否 |  |  |
| forceUpdate | 是否强制重定位(false变成true的过程会触发重定位) | boolean | 否 |  |  |
| blacklist | 禁止关闭弹层的触发器区域容器标记，如['div[id="PhotoView_Slider"]'](黑名单) | Array<string> | 否 |  |  |
| childrenHoverBlacklist | 在自定义渲染时，children中禁止关闭弹层的触发器区域容器标记，如['div[id="PhotoView_Slider"]'](黑名单) | Array<string> | 否 |  |  |
| enableLocationCalculation | 启用位置计算方案 | boolean | 否 |  |  |
| showAction | 打开弹出框动作,可选`contextMenu`、`mouseEnter`、`focus`、`click` | string | string[] |  |  |
| hideAction | 关闭弹出框动作,可选`mouseLeave`、`blur`、`click` | string | string[] |  |  |
| mouseEnterDelay | 鼠标移入打开弹层延时，单位：秒 | number |  | 0 |  |
| mouseLeaveDelay | 鼠标移出关闭弹层延时，单位：秒 | number |  | 0.1 |  |
| noAlign | 无需定位，popover底部弹出框 | boolean |  |  |  |
| onAdjustedPlacement | 自适应调整位置回调事件 | (placement: PopupPlacement, target: HTMLElement, sourceRegion: Region) => void |  |  |  |
| target | 自定义弹层容器根节点 | HTMLElement |  |  |  |
| prohibitPreventDefault | 禁止点击冒泡(action=click模式生效) | boolean |  |  |  |
| enableWheelEventEmitter | 启用鼠标滚动监听关闭弹层方案 | boolean |  |  |  |
| followScroll | 是否跟随滚动条滚动 | boolean | 否 | false |  |
| destroyOnClose | 关闭即销毁 | boolean | 否 | false |  |
| stopPopupPropagation | 取消popup点击冒泡 | boolean | 否 | false |  |
| prohibitCalculatingBodyOffset | 禁止计算body偏移量 | boolean | 否 | false |  |
| offset | 自定义弹层定位偏移量 | AnyObj | 否 |  |  |
| useFixedMiddlePopupPlacement | 在弹层面板过大的情况下是否在屏幕正中间展示，如果不开启则按照默认位置展示 | boolean | 否 |  |  |
### 一、forceUpdate 说明

```
forceUpdate: 当参数由false变成true时会触发重定位，一般用于定位结束后，弹层内容发生变化，需再次重定位的场景。重定位会改变元素的几何属性，从而进行重排和重绘，因此需控制触发生效的时机，尽可能少的重定位。
```

### 二、getPopupContainer 与 maskClosable 参数不可共同使用

### 三、PopupPlacement 说明如下：

```
type PopupPlacement = 'left' | 'right' | 'top' | 'bottom' | 'topLeft' | 'topRight' | 'bottomRight' | 'bottomLeft' | 'leftTop' | 'rightTop' | 'leftBottom' | 'rightBottom' | 'middle'
```

### 四、弹框显隐事件监听

```
使用方式：
  1. 添加监听事件：eventEmitter.addListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  2. 卸载监听事件：eventEmitter.removeListener(uiAppName, Trigger.EVENT_VISIBLE_CHANGE, this.onVisibleChange)
  3. onVisibleChange示例方法：onVisibleChange = (customEventOptions: any) => {
    if (customEventOptions && customEventOptions.detail) {
      console.log(customEventOptions.detail.visible)
    }
  }
  4. 组件需设置enableEventEmitter=true
demo参考基础用法案例
```
