ion-popover
弹出框(Popover)是出现在当前页面上方的对话框。它可以用于任何事情,但通常用于导航栏中放不下的溢出操作。
有两种使用 ion-popover 的方式:内联或通过 popoverController。每种方法都有不同的考虑因素,因此请确保使用最适合你用例的方法。
内联弹出框
ion-popover 可以直接在模板中编写组件来使用。这减少了你需要连接以呈现弹出框的处理程序数量。
在 Angular、React 或 Vue 中使用 ion-popover 时,你传入的组件将在弹出框关闭时被销毁。由于此功能由 JavaScript 框架提供,在没有 JavaScript 框架的情况下使用 ion-popover 不会销毁你传入的组件。如果需要此功能,我们建议使用 popoverController。
何时使用
当你不想显式连接点击事件来打开弹出框时,内联使用弹出框非常有用。例如,你可以使用 trigger 属性指定一个在点击时应呈现弹出框的按钮。你还可以使用 trigger-action 属性来自定义弹出框是在左键单击、右键单击还是悬停时呈现。
如果你需要对弹出框的呈现和关闭进行精细控制,我们建议使用 popoverController。
Angular
由于你传入的组件需要在呈现弹出框时创建,在关闭时销毁,我们无法在内部使用 <ng-content> 来投影内容。相反,我们使用期望传入 <ng-template> 的 <ng-container>。因此,在传入组件时,你需要将其包裹在 <ng-template> 中:
<ion-popover [isOpen]="isPopoverOpen">
<ng-template>
<app-popover-content></app-popover-content>
</ng-template>
</ion-popover>
触发器
内联 ion-popover 的触发器是在交互时会打开弹出框的元素。交互行为可以通过设置 trigger-action 属性来自定义。请注意,trigger-action="context-menu" 将阻止系统的默认上下文菜单打开。
触发器不适用于使用 popoverController 的情况,因为 ion-popover 不是提前创建的。
isOpen 属性
内联弹出框也可以通过将 isOpen 属性设置为 true 来打开。如果你需要比使用触发器更精细地控制弹出框,可以使用此方法。
isOpen 使用单向数据绑定,这意味着当弹出框关闭时,它不会自动设置为 false。开发者应监听 ionPopoverDidDismiss 或 didDismiss 事件,并将 isOpen 设置为 false。这样做的原因是防止 ion-popover 的内部实现与应用状态紧密耦合。使用单向数据绑定时,弹出框只需要关心响应式变量提供的布尔值。而使用双向数据绑定时,弹出框需要同时关心布尔值和响应式变量本身的存在性,这可能导致不确定的行为并使应用更难调试。
控制器弹出框
通过使用从 Ionic 框架导入的 popoverController,也可以以编程方式呈现 ion-popover。这让你可以完全控制弹出框何时呈现,超越了内联弹出框给你的自定义程度。
何时使用
我们通常建议你内联编写弹出框,因为它简化了应用中的代码量。只有在编写内联弹出框不切实际的复杂用例中,才应使用 popoverController。使用控制器时,你的弹出框不是提前创建的,因此 trigger 和 trigger-action 等属性在此不适用。此外,嵌套弹出框与控制器的方案不兼容,因为调用 create 方法时弹出框会自动添加到应用的根部。
React
React 没有一个控制器,而是有一个名为 useIonPopover 的钩子,其行为类似。请注意,useIonPopover 需要是 <IonApp> 的后代。如果你需要在 <IonApp> 外部使用弹出框,请考虑使用内联弹出框。
用法
控制台控制台消息将在上方示例中调用 console.log 时显示在此处。样式
弹出框在应用的根部呈现,因此它们覆盖整个应用。此行为适用于内联弹出框和从控制器呈现的弹出框。因此,自定义弹出框样式不能限定到特定组件,因为它们不会应用于弹出框。相反,样式必须全局应用。对于大多数开发者来说,将自定义样式放在 global.css 中就足够了。
如果你正在构建 Ionic Angular 应用,样式需要添加到全局样式表文件中。
定位
参考点
呈现弹出框时,Ionic 框架需要一个参考点来相对于其呈现弹出框。使用 reference="event" 时,弹出框将相对于在触发器元素上分派的指针事件的 x-y 坐标呈现。使用 reference="trigger" 时,弹出框将相对于触发器元素的边界框呈现。
方向
无论你选择何种参考点,都可以使用 side 属性将弹出框定位到参考点的 top、right、left 或 bottom。如果希望方向根据 LTR 或 RTL 模式切换,也可以使用 start 或 end 值。
对齐
alignment 属性允许你将弹出框的一个边缘与触发器元素上的相应边缘对齐。使用的确切边缘取决于 side 属性的值。
方向和对齐演示
偏移
如果你需要对弹出框的定位进行更精细的控制,可以使用 --offset-x 和 --offset-y CSS 变量。例如,--offset-x: 10px 将弹出框内容向右移动 10px。
尺寸
制作下拉菜单时,你可能希望弹出框的宽度与触发器元素的宽度匹配。在不提前知道触发器宽度的情况下做到这一点很棘手。你可以将 size 属性设置为 'cover',Ionic 框架将确保弹出框的宽度与触发器元素的宽度匹配。
如果你使用 popoverController,必须通过 event 选项提供事件,Ionic 框架将使用 event.target 作为参考元素。请参阅控制器演示了解此模式的示例。
嵌套弹出框
内联使用 ion-popover 时,可以嵌套弹出框以创建嵌套下拉菜单。这样做时,只有第一个弹出框的背景遮罩会显示,这样屏幕不会随着打开更多弹出框而逐渐变暗。
你可以使用 dismissOnSelect 属性在点击弹出框内容时自动关闭弹出框。此行为不适用于点击另一个弹出框的触发器元素。
使用 popoverController 时无法创建嵌套弹出框,因为调用 create 方法时弹出框会自动添加到应用的根部。
接口
以下是在使用 popoverController 时可用的所有选项。这些选项应在调用 popoverController.create() 时提供。
interface PopoverOptions {
component: any;
componentProps?: { [key: string]: any };
showBackdrop?: boolean;
backdropDismiss?: boolean;
translucent?: boolean;
cssClass?: string | string[];
event?: Event;
animated?: boolean;
mode?: 'ios' | 'md';
keyboardClose?: boolean;
id?: string;
htmlAttributes?: { [key: string]: any };
enterAnimation?: AnimationBuilder;
leaveAnimation?: AnimationBuilder;
size?: PopoverSize;
dismissOnSelect?: boolean;
reference?: PositionReference;
side?: PositionSide;
alignment?: PositionAlign;
arrow?: boolean;
}
类型
以下是 ion-popover 的所有自定义类型:
type PopoverSize = 'cover' | 'auto';
type TriggerAction = 'click' | 'hover' | 'context-menu';
type PositionReference = 'trigger' | 'event';
type PositionSide = 'top' | 'right' | 'bottom' | 'left' | 'start' | 'end';
type PositionAlign = 'start' | 'center' | 'end';
无障碍访问
键盘交互
ion-popover 具有基本的键盘支持,用于在弹出框内的可聚焦元素之间导航。下表详细说明了每个键的作用:
| 键 | 描述 |
|---|---|
| Tab | 将焦点移动到下一个可聚焦元素。 |
| Shift + Tab | 将焦点移动到上一个可聚焦元素。 |
| Esc | 关闭弹出框。 |
| Space 或 Enter | 点击可聚焦元素。 |
ion-popover 具有完整的方向键支持,用于在具有 button 属性的 ion-item 元素之间导航。最常见的用例是作为桌面应用中的下拉菜单。除了基本的键盘支持外,下表详细说明了下拉菜单的方向键支持:
| 键 | 描述 |
|---|---|
| 上箭头 | 将焦点移动到上一个可聚焦元素。 |
| 下箭头 | 将焦点移动到下一个可聚焦元素。 |
| Home | 将焦点移动到第一个可聚焦元素。 |
| End | 将焦点移动到最后一个可聚焦元素。 |
| 左箭头 | 在子弹出框中使用时,关闭弹出框并将焦点返回到父弹出框。 |
| Space、Enter 和 右箭头 | 当聚焦触发器元素时,打开关联的弹出框。 |
性能
挂载内部内容
内联 ion-popover 的内容在关闭时会被卸载。如果此内容渲染成本高,开发者可以使用 keepContentsMounted 属性,在弹出框挂载时立即挂载内容。这有助于优化应用的响应速度,因为在弹出框打开时内部内容已经挂载。
开发者在使用 keepContentsMounted 时应记住以下几点:
-
此功能应作为处理现有性能问题的最后手段。在使用此功能之前,请尝试识别并解决性能瓶颈。此外,不要使用此功能来预判性能问题。
-
此功能仅在使用 JavaScript 框架时需要。未使用框架的开发者可以将要渲染的内容传递给弹出框,内容将自动渲染。
-
此功能仅适用于内联弹出框。使用
popoverController创建的弹出框不是提前创建的,因此内部内容也不会创建。 -
内部组件上的任何 JavaScript 框架生命周期钩子将在弹出框挂载时立即运行,而不是在弹出框呈现时。
属性
alignment
| 说明 | Describes how to align the popover content with the reference point. Defaults to "center" for ios mode, and "start" for md mode. |
| 属性 | alignment |
| 类型 | "center" | "end" | "start" | undefined |
| 默认值 | undefined |
animated
| 说明 | If true, the popover will animate. |
| 属性 | animated |
| 类型 | boolean |
| 默认值 | true |
arrow
| 说明 | If true, the popover will display an arrow that points at the reference when running in ios mode. Does not apply in md mode. |
| 属性 | arrow |
| 类型 | boolean |
| 默认值 | true |
backdropDismiss
| 说明 | If true, the popover will be dismissed when the backdrop is clicked. |
| 属性 | backdrop-dismiss |
| 类型 | boolean |
| 默认值 | true |
component
| 说明 | The component to display inside of the popover. You only need to use this if you are not using a JavaScript framework. Otherwise, you can just slot your component inside of ion-popover. |
| 属性 | component |
| 类型 | Function | HTMLElement | null | string | undefined |
| 默认值 | undefined |
componentProps
| 说明 | The data to pass to the popover component. You only need to use this if you are not using a JavaScript framework. Otherwise, you can just set the props directly on your component. |
| 属性 | undefined |
| 类型 | undefined | { [key: string]: any; } |
| 默认值 | undefined |
dismissOnSelect
| 说明 | If true, the popover will be automatically dismissed when the content has been clicked. |
| 属性 | dismiss-on-select |
| 类型 | boolean |
| 默认值 | false |
enterAnimation
| 说明 | Animation to use when the popover is presented. |
| 属性 | undefined |
| 类型 | ((baseEl: any, opts?: any) => Animation) | undefined |
| 默认值 | undefined |
event
| 说明 | The event to pass to the popover animation. |
| 属性 | event |
| 类型 | any |
| 默认值 | undefined |
htmlAttributes
| 说明 | Additional attributes to pass to the popover. |
| 属性 | undefined |
| 类型 | undefined | { [key: string]: any; } |
| 默认值 | undefined |
isOpen
| 说明 | If true, the popover will open. If false, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the trigger property. Note: isOpen will not automatically be set back to false when the popover dismisses. You will need to do that in your code. |
| 属性 | is-open |
| 类型 | boolean |
| 默认值 | false |
keepContentsMounted
| 说明 | If true, the component passed into ion-popover will automatically be mounted when the popover is created. The component will remain mounted even when the popover is dismissed. However, the component will be destroyed when the popover is destroyed. This property is not reactive and should only be used when initially creating a popover.Note: This feature only applies to inline popovers in JavaScript frameworks such as Angular, React, and Vue. |
| 属性 | keep-contents-mounted |
| 类型 | boolean |
| 默认值 | false |
keyboardClose
| 说明 | If true, the keyboard will be automatically dismissed when the overlay is presented. |
| 属性 | keyboard-close |
| 类型 | boolean |
| 默认值 | true |
leaveAnimation
| 说明 | Animation to use when the popover is dismissed. |
| 属性 | undefined |
| 类型 | ((baseEl: any, opts?: any) => Animation) | undefined |
| 默认值 | undefined |
mode
| 说明 | The mode determines which platform styles to use. 这是一个虚拟属性,在初始化时设置一次,之后更改其值不会更新组件。 |
| 属性 | mode |
| 类型 | "ios" | "md" |
| 默认值 | undefined |
reference
| 说明 | Describes what to position the popover relative to. If "trigger", the popover will be positioned relative to the trigger button. If passing in an event, this is determined via event.target. If "event", the popover will be positioned relative to the x/y coordinates of the trigger action. If passing in an event, this is determined via event.clientX and event.clientY. |
| 属性 | reference |
| 类型 | "event" | "trigger" |
| 默认值 | 'trigger' |
showBackdrop
| 说明 | If true, a backdrop will be displayed behind the popover. This property controls whether or not the backdrop darkens the screen when the popover is presented. It does not control whether or not the backdrop is active or present in the DOM. |
| 属性 | show-backdrop |
| 类型 | boolean |
| 默认值 | true |
side
| 说明 | Describes which side of the reference point to position the popover on. The "start" and "end" values are RTL-aware, and the "left" and "right" values are not. |
| 属性 | side |
| 类型 | "bottom" | "end" | "left" | "right" | "start" | "top" |
| 默认值 | 'bottom' |
size
| 说明 | Describes how to calculate the popover width. If "cover", the popover width will match the width of the trigger. If "auto", the popover width will be set to a static default value. |
| 属性 | size |
| 类型 | "auto" | "cover" |
| 默认值 | 'auto' |
translucent
| 说明 | If true, the popover will be translucent. Only applies when the mode is "ios" and the device supports backdrop-filter. |
| 属性 | translucent |
| 类型 | boolean |
| 默认值 | false |
trigger
| 说明 | An ID corresponding to the trigger element that causes the popover to open. Use the trigger-action property to customize the interaction that results in the popover opening. |
| 属性 | trigger |
| 类型 | string | undefined |
| 默认值 | undefined |
triggerAction
| 说明 | Describes what kind of interaction with the trigger that should cause the popover to open. Does not apply when the trigger property is undefined. If "click", the popover will be presented when the trigger is left clicked. If "hover", the popover will be presented when a pointer hovers over the trigger. If "context-menu", the popover will be presented when the trigger is right clicked on desktop and long pressed on mobile. This will also prevent your device's normal context menu from appearing. |
| 属性 | trigger-action |
| 类型 | "click" | "context-menu" | "hover" |
| 默认值 | 'click' |
事件
| Name | 说明 | 冒泡 |
|---|---|---|
didDismiss | Emitted after the popover has dismissed. Shorthand for ionPopoverDidDismiss. | true |
didPresent | Emitted after the popover has presented. Shorthand for ionPopoverWillDismiss. | true |
ionPopoverDidDismiss | Emitted after the popover has dismissed. | true |
ionPopoverDidPresent | Emitted after the popover has presented. | true |
ionPopoverWillDismiss | Emitted before the popover has dismissed. | true |
ionPopoverWillPresent | Emitted before the popover has presented. | true |
willDismiss | Emitted before the popover has dismissed. Shorthand for ionPopoverWillDismiss. | true |
willPresent | Emitted before the popover has presented. Shorthand for ionPopoverWillPresent. | true |
方法
dismiss
| 说明 | Dismiss the popover overlay after it has been presented. |
| 签名 | dismiss(data?: any, role?: string, dismissParentPopover?: boolean) => Promise<boolean> |
| 参数 | data: Any data to emit in the dismiss events. role: The role of the element that is dismissing the popover. For example, 'cancel' or 'backdrop'. dismissParentPopover: If true, dismissing this popover will also dismiss a parent popover if this popover is nested. Defaults to true.This is a no-op if the overlay has not been presented yet. If you want to remove an overlay from the DOM that was never presented, use the remove method. |
onDidDismiss
| 说明 | Returns a promise that resolves when the popover did dismiss. |
| 签名 | onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>> |
onWillDismiss
| 说明 | Returns a promise that resolves when the popover will dismiss. |
| 签名 | onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>> |
present
| 说明 | Present the popover overlay after it has been created. Developers can pass a mouse, touch, or pointer event to position the popover relative to where that event was dispatched. |
| 签名 | present(event?: MouseEvent | TouchEvent | PointerEvent | CustomEvent) => Promise<void> |
CSS 阴影部分
| Name | 说明 |
|---|---|
arrow | The arrow that points to the reference element. Only applies on ios mode. |
backdrop | The ion-backdrop element. |
content | The wrapper element for the default slot. |
CSS 自定义属性
| Name | 说明 |
|---|---|
--backdrop-opacity | Opacity of the backdrop |
--background | Background of the popover |
--box-shadow | Box shadow of the popover |
--height | Height of the popover |
--max-height | Maximum height of the popover |
--max-width | Maximum width of the popover |
--min-height | Minimum height of the popover |
--min-width | Minimum width of the popover |
--offset-x | The amount to move the popover by on the x-axis |
--offset-y | The amount to move the popover by on the y-axis |
--width | Width of the popover |
插槽
| Name | 说明 |
|---|---|
Content is placed inside of the .popover-content element. |