ext-ui.com

第一个自定义组件例子

在Ext JS中,构建自定义组件是扩展框架功能和创建可重复使用的模块化 UI 元素以满足应用程序的特定需求的有效方法。

它们是用户定义的类,用于扩展现有的 Ext JS 组件或基类,允许开发人员将布局、逻辑、配置和行为封装到可重用的构建块中。这些组件通常通过扩展 Ext.Component、Ext.panel.Panel 或任何其他核心小部件来创建。它们可以轻松集成到更大的应用程序中。
它们通过以下方式提高可维护性和一致性:

  • 将逻辑和 UI 封装在一个地方
  • 允许跨多个视图或应用程序重用
  • 支持标准 Ext JS 功能,如事件处理、数据绑定和布局管理

最佳实践


在 Ext JS 中开发自定义组件时,遵循一致的结构和命名约定有助于保持代码清晰度、可重用性和可扩展性。

在专用文件夹中组织组件


虽然 Ext JS 允许你将组件保存在项目文件夹结构中的任何位置,但强烈建议将自定义组件放置在专用文件夹中,通常名为 ux(用户扩展的缩写)。这样可以清楚地区分自定义组件与核心 Ext JS 类和特定于应用程序的视图。
推荐的文件夹结构:
App/ux/ComponentName.js

使用一致的命名约定


自定义组件应遵循一致且描述性的命名模式。一个好的命名规范是,以应用的命名空间作为前缀,后接 ux,最后是采用 PascalCase 命名法的组件名称。
例子:
  • App.ux.时间线,
  • App.ux.DataGrid,
  • App.ux.FilterPanel
这使得组件易于识别,并避免与内置或第三方组件发生命名冲突。

扩展最相关的基类


始终从与目标功能紧密匹配的现有 Ext JS 类进行扩展。这样可以最大限度地减少需要编写的代码量,并确保更好地与 Ext JS 生态系统集成。 例如,如果您正在构建自定义数据显示面板,则可以从 Ext.panel.Panel 或 Ext.dataview.DataView 进行扩展。

使用 config 属性定义本地参数


所有可配置选项和本地参数都应在 config 块下定义。这可确保您的组件与 Ext JS 的配置系统兼容,从而实现自动 getter/setter 生成、事件绑定和响应式更新。
config: {
	title: 'Default Title',
	data: null,
	scrollable: true
}

这种方法可以使您的组件保持干净、易于管理,并且开发人员可以轻松配置。

灵活性和可重用性设计


尽可能提高组件的灵活性和可配置性。避免对值或行为进行硬编码;相反,应该公开一些属性、事件和钩子,以便用户视图能够自定义或覆盖它们。
需要考虑灵活性的关键领域:
  • 允许覆盖模板(tpl)或布局选项
  • 提供数据源或显示逻辑的配置
  • 发出自定义事件以通知父组件状态变化
  • 避免与特定模型、存储或控制器紧密耦合
通过考虑可重用性进行设计,您可以增加组件在不同模块和项目中的寿命和实用性。

包含自定义 CSS


如果您的组件使用自定义 CSS:
  • 确保样式有作用域
  • 使用 sencha 命令重建并刷新应用程序以应用样式
  • 或者,运行 sencha app watch 自动编译你的 CSS 并使你的应用与更改保持同步

记录你的组件


文档对于长期可维护性至关重要。您的组件类应该包含:

清晰描述其目的
可用配置选项列表
它处理的事件
公共方法及其预期用途


内联 JSDoc 注释对于 IDE 和代码阅读器都很有帮助。

提供使用示例


包含一个示例实现或使用块(在注释或演示文件中)来演示如何实例化和配置组件。

第一个例子。毫无意义的组件


Pointless 组件是一个精心设计的、适合初学者的自定义组件,它通过扩展 Ext JS 中的 Ext.Button 类来构建。虽然它的功能可能很少,甚至可以说“毫无意义”,但它却服务于一个重要的目的:介绍 Ext JS 中组件创建和配置的基本概念。

它的作用


这个自定义组件的作用类似于标准按钮,但具有一些额外的功能:
  • 每次单击该按钮时,其标签都会更新以反映倒计时。
  • 例如,如果它从 5 开始,单击它会将文本更改为 4,然后是 3,依此类推。
虽然在实际应用中没有用,但这种行为使我们能够探索关键的开发概念。

组件


/**
 * @class App.ux.useless.PointlessButton
 * @extends Ext.button.Button
 * @xtype pointless-button
 *
 * A simple and intentionally "pointless" custom button component that demonstrates
 * basic Ext JS component principles such as configuration, event handling, and state management.
 *
 * With each click, the button decrements its `value` and updates its displayed text.
 *
 * ## Example usage:
 * ```javascript
 * {
 *     xtype: 'pointless-button',
 *     value: 10 // optional starting value, defaults to 100
 * }
 * ```
 */
Ext.define('App.ux.useless.PointlessButton', {
    extend: 'Ext.button.Button',
    xtype: 'pointless-button',
    /**
     * @cfg {Number} value
     * The initial numeric value to display and decrement with each click.
     * Defaults to `100` if not provided.
     */
    config: {
        value: 100
    },
    /**
     * @property {String} text
     * The text label of the button, which is updated based on `value`.
     */
    text: '',
    /**
     * @event click
     * Fired when the button is clicked. Decrements the `value` by 1 (until it reaches 0)
     * and updates the button's text to reflect the new value.
     */
    listeners: {
        click: function () {
            if (this.value > 0) {
                this.value--;
            }
            this.setText(this.value);
        }
    },
    /**
     * Initializes the component and sets the initial button text based on the `value`.
     * Called automatically during the component lifecycle.
     *
     * @protected
     */
    initComponent: function () {
        this.callParent();
        this.setText(this.value);
    }
});

用法


使用该组件非常简单,就像包含任何标准 Ext JS 组件一样。只需引用其 xtype 并传递所需的任何自定义配置即可。
{
    xtype: 'pointlesscomponent',
    count: 3 // starts at 3 instead of the default 5
}

这将使 Pointless Component 的起始计数为 3。每次点击都会使该数字减少,直到达到零。

我们学到了什么


我们刚刚创建的Pointless Component演示了几个重要的 Ext JS 原则:

创建自定义组件


  • 扩展现有的基类(Ext.Button)来创建新的组件。
  • 使用 Ext.define 在 Ext JS 中引入继承和类结构。

接收和使用参数


  • 我们使用配置对象来定义初始参数(例如,起始计数)。
  • 了解了如何将值传递到组件并在逻辑中访问它们。

处理事件并更新状态


  • 通过绑定点击事件,我们触发了组件 UI 的变化。
  • 这说明了事件处理、动态更新 UI和有状态行为。

后续步骤


这是构建自定义 Ext JS 组件系列教程(共五部分)的第一部分。
在下一篇教程中,我们将更进一步,使用Classic Toolkit 创建一个切换按钮。

英文原文:https://www.sencha.com/blog/custom-components-introduction-and-first-example/