弹出窗口在技术上并非一个组件。它更像是 ReactXP.App 命名空间中的一组方法,允许应用程序显示一个覆盖屏幕一部分的视图。弹出窗口可以“锚定”到已挂载的组件,并随组件在屏幕上移动(例如,响应滚动事件)。
当显示弹出窗口时,调用者会指定一个 PopupOptions 结构,其中包含多个回调,包括 renderPopup 方法。
弹出窗口默认不会像开关一样操作。当调用 Popup.show 时,它将始终显示弹出窗口。如果需要弹出窗口像开关一样操作,则应将 PopupOptions.dismissIfShown 设置为 true。在这种情况下,如果组件为弹出窗口调用 Popup.show 一次,它将显示弹出窗口。同一组件后续的调用将关闭弹出窗口,依此类推。
弹出窗口的整体尺寸在其生命周期内被假定保持不变。这允许只测量一次尺寸,然后弹出窗口可以相对于锚点进行定位。
弹出窗口由调用者指定的一个唯一 ID 标识。
// 'context' mode makes it attempt to behave like a context menu -- defaulting
// to the lower right of the anchor element and working its way around. It is not supported
// with inner positioning and will throw an exception if used there.
type PopupPosition = 'top' | 'right' | 'bottom' | 'left' | 'context';
interface PopupOptions {
// Returns a mounted component instance that serves as the
// "anchor" for the popup. Often a button.
getAnchor: () => React.Component<any, any>;
// Renders the contents of the popup. This is called twice. The
// first time it is called, the parameters are all defaults
// (default position and 0 offset and dimensions). This allows
// the popup to be measured and positioned. It is called a second
// time with the position, offset and dimensions specified. This
// allows the method to modify the appearance based on these
// parameters. The dimensions should not be modified, however.
renderPopup: (anchorPosition: PopupPosition, anchorOffset: number,
popupWidth: number, popupHeight: number) => ReactNode;
// Returns a mounted component instance that controls the triggering
// of the popup. In the majority of cases, "anchor" of popup has
// handlers to control when the popup will be seen and this function
// is not required. In a few cases, where anchor is not the same as
// the whole component that triggers when the popup wil be seen,
// this can be used. For instance, a button combined with a chevron
// icon, which on click triggers a popup below the chevron icon. In
// this example, getElementTriggeringPopup() can return the container
// with button and chevron icon.
getElementTriggeringPopup?: () => React.Component<any, any>;
// Called when the popup is dismissed. Popup.isDisplayed() will return
// false for the popup being dismissed when this callback runs.
onDismiss?: () => void;
// Prioritized order of positions. Popup is positioned
// relative to the anchor such that it remains on screen.
// Default is ['bottom', 'right', 'top', 'left'].
positionPriorities?: string[];
// Position the popup inside its anchor.
// In this mode only the first position priority will be used.
useInnerPositioning?: boolean;
// On pressed handler to notify whoever wanted to create the popup
// that its anchor has been pressed.
// IMPORTANT NOTE: This handler may be called when the component is
// already unmounted as it uses a time delay accommodate
// fade-out animations.
onAnchorPressed?: (e: SyntheticEvent) => void;
// Determines if the anchor invoking the popup should behave like a toggle.
// If true, calling Popup.show will show the popup. A subsequent call
// will hide the popup. If false or undefined (default), calling Popup.show
// will always show the popup.
dismissIfShown?: boolean;
// By default, clicks or taps outside of a popup (unless they are on the
// anchor) will not dismiss the active popup. If true, this overrides the
// default behavior, in which case the popup must be dismissed explicitly.
preventDismissOnPress?: boolean;
// The popup may be left in the DOM after it's dismissed. This is a
// performance optimization to make the popup appear faster when it's shown
// again, intended for popups that tend to be shown repeatedly. Note that
// this is only a hint, so callers shouldn't rely on caching behavior.
cacheable?: boolean;
// Android, iOS, and Windows only.
// The id of the root view this popup is associated with.
// Defaults to the view set by UserInterface.setMainView();
rootViewId?: string;
}
// Dismisses an already-displayed popup after a specified number
// of milliseconds
autoDismiss(popupId: string, dismissDelay: number = 0): void;
// Dismisses an already-displayed popup immediately
dismiss(popupId: string): void;
// Dismisses all popups immediately
dismissAll(): void;
// Displays a popup. Returns true if successful, false if the popup is
// already displayed
show(options: PopupOptions, popupId: string, showDelay: number = 0): boolean;
// Indicates whether the specified popup is displayed. If no id provided indicates if some popup is displayed.
isDisplayed(popupId?: string): boolean;
const _popupId = 'myPopup';
let _popupDisplayed = false;
onHoverStart() {
if (!this._popupDisplayed) {
this.displayPopup();
}
};
onHoverEnd() {
RX.Popup.autoDismiss(_popupId, 2000);
};
displayPopup() {
let popupOptions: RX.Types.PopupOptions = {
getAnchor: () => {
return this._mountedButton;
},
renderPopup: (anchorPosition: Types.PopupPosition, anchorOffset: number,
popupWidth: number, popupHeight: number) => {
return this._renderPopupView(anchorPosition,
anchorOffset, popupWidth, popupHeight);
},
positionPriorities: ['right', 'left', 'bottom', 'top'],
onDismiss: () => {
this._popupDisplayed = false;
}
};
RX.Popup.show(popupOptions, _popupId, 500);
this._popupDisplayed = true;
}