菜单

组件系统

相关源文件

Ionic Framework 组件系统定义了 UI 组件的构建、打包和向不同 JavaScript 框架公开的方式。本文档解释了 Ionic 基于 Web Component 的架构和实现,包括组件的定义、编译以及与 Angular、React 和 Vue 的集成。

有关特定 UI 组件的信息,请参阅第 2 部分(核心组件)中的相应页面。

架构概述

Ionic 组件系统基于 Web Component 构建,并使用 Stencil 作为编译器。这种方法允许 Ionic 维护单一的代码库,同时为 Angular、React 和 Vue 提供特定框架的适配器。

来源: core/src/components.d.ts core/stencil.config.ts

核心组件实现

Ionic 组件使用 Stencil 实现为 Web Components,Stencil 提供了一个类似 Angular 的声明式 API,但会编译为标准的 Web Components。

来源: core/src/components/input/input.tsx core/src/components/select/select.tsx core/src/components/checkbox/checkbox.tsx

组件定义

组件使用 Stencil 的 @Component 装饰器进行定义,该装饰器指定了标签名、样式和 Shadow DOM 封装策略。以下是一个典型的组件结构。

组件使用几个关键的装饰器

装饰器模式(Decorator)目的示例
@Prop()可以从 HTML 设置的公共属性@Prop() disabled = false;
@State()未暴露给用户的内部状态@State() hasFocus = false;
@Event()组件发出的事件@Event() ionChange!: EventEmitter<InputChangeEventDetail>;
@Method()可以从 JavaScript 调用公共方法@Method() async setFocus() { ... }
@Watch()属性更改时触发@Watch('value') valueChanged() { ... }
@Element()对宿主 DOM 元素的引用@Element() el!: HTMLIonInputElement;

来源: core/src/components/input/input.tsx25-33 core/src/components/select/select.tsx core/src/components/checkbox/checkbox.tsx

组件生命周期

Ionic 组件遵循 Stencil 的组件生命周期,其中关键方法在组件生命周期的不同阶段运行。

来源: core/src/components/input/input.tsx366-427 core/src/components/select/select.tsx278-330

类型系统

Stencil 会自动为所有组件生成 TypeScript 定义,这在使用组件时提供了类型检查和自动补全功能。

组件接口

生成的 components.d.ts 文件包含了每个组件属性、事件和方法的接口。

来源: core/src/components.d.ts7-46

组件样式系统

Ionic 组件使用 CSS 变量进行样式和主题设置,这使得自定义变得容易。

CSS 封装

组件使用以下三种封装策略之一

  • shadow:使用 Shadow DOM 进行完整的样式封装
  • scoped:应用基于属性的样式作用域
  • none:无封装,样式影响全局范围

来源: core/src/components/input/input.tsx core/src/components/select/select.tsx

CSS 自定义属性

组件公开 CSS 自定义属性(CSS 变量)用于样式设置。

这些 CSS 变量可由用户自定义。

来源: core/src/components/select/select.scss6-44

框架集成

Ionic 组件作为 Web Components 分发在 @ionic/core 包中,但特定框架的包会适配这些组件,使其能够自然地与每个框架协同工作。

框架适配器

每个支持的框架都有一个包,提供核心 Web Components 的包装器。

来源: packages/angular/src/directives/proxies.ts packages/react/src/components/proxies.ts packages/vue/src/proxies.ts

代理生成

框架适配器通过 Stencil 配置中的输出目标插件生成。

来源: core/stencil.config.ts72-210

特定于框架的行为

每个框架都有独特集成需求。

Angular

Angular 组件被创建为具有 @Input()@Output() 绑定的指令,这些绑定映射到 Web Component 的属性和事件。

来源: packages/angular/src/directives/proxies.ts1-50

React

React 组件包装了 Web Components,并提供了 React 特有的功能,如 refs 和事件处理。

来源: packages/react/src/components/proxies.ts1-20

Vue

Vue 组件包含对 v-model 和其他 Vue 特有功能的特殊处理。

来源: packages/vue/src/proxies.ts87-109

组件特性

Ionic 组件提供了多项功能来增强组件的可用性。

Shadow Parts(Shadow 节点)

组件定义了“parts”,允许在 shadow DOM 内进行定向样式设置。

来源: core/src/components/select/select.tsx40-47

Slots(插槽)

组件使用插槽来允许将内容放置在组件的特定部分。

来源: core/src/components/select/select.tsx36-38 core/src/components/input/input.tsx21-24

表单集成

Ionic 组件与原生表单和特定框架的表单系统集成。

表单组件,如输入框、复选框和选择框,会渲染隐藏的原生输入框以兼容标准的 HTML 表单。

来源: core/src/components/input/input.tsx301-305 core/src/components/checkbox/checkbox.tsx56-86

组件解剖示例

这是典型的 Ionic 组件结构的示例,以 ion-input 为例

来源: core/src/components/input/input.tsx

属性

组件公开的属性可以通过 HTML 属性或框架属性来设置

属性是在组件类中使用 @Prop() 装饰器定义的

来源: core/src/components/input/input.tsx70-290

方法

组件公开方法,用于程序化交互

来源: core/src/components/input/input.tsx442-462

事件

组件会发出事件,可以进行监听

这些事件可以通过特定于框架的方式进行处理

来源: core/src/components/input/input.tsx302-328

组件打包

组件被打包成逻辑分组,以实现最佳加载

这种打包方式确保了相关组件一起加载,优化了性能。

来源: core/stencil.config.ts77-118

破坏性变更

组件系统会随着时间的推移而发展,并记录了破坏性更改,以帮助开发人员在版本之间进行迁移

主要版本可能会更改组件 API、样式或框架集成。BREAKING.md 文件提供了详细的迁移指南。

来源: BREAKING.md156-158

总结

Ionic 组件系统是一个强大、结构良好的系统,用于构建跨框架的 UI 组件。它使用 Web Components(通过 Stencil)作为其基础,并提供特定于框架的适配器,以与 Angular、React 和 Vue 进行自然的集成。这种方法允许 Ionic 维护单一的核心代码库,同时为每个支持的框架提供优化的开发人员体验。