文档帮助

术语、图标和标签

许多类在使用配置对象创建(实例化)类时都有快捷名称。快捷名称被称为 alias(别名)(如果类扩展了 Ext.Component,则为 xtype)。别名/xtype 列在适用类的类名旁边,以便快速参考。

访问级别

框架类或其成员可以指定为 private(私有的)或 protected(受保护的)。否则,类/成员是 public(公共的)。Publicprotectedprivate 是访问描述符,用于传达类或类成员应如何以及何时使用。

成员类型

成员语法

下面是一个示例类成员,我们可以对其进行剖析,以展示类成员的语法(在本例中是从 Ext.button.Button 类查看的 lookupComponent 方法)。

lookupComponent ( item ) : Ext.Component
受保护的

当原始配置对象添加到此容器时调用,无论是在初始化 items 配置期间,还是在 added) 或 {@link #insert 插入新项目时。

此方法将传递的对象转换为实例化的子组件。

当需要对子组件创建应用特殊处理时,可以在子类中覆盖此方法。

参数

item :  Object

正在添加的配置对象。

返回值
Ext.Component

要添加的组件。

让我们看一下成员行的每个部分

成员标志

API 文档使用许多标志来进一步传达类成员的功能和意图。标签可以用文本标签、缩写或图标表示。

类图标

- 表示框架类

- 单例框架类。*有关更多信息,请参阅单例标志

- 组件类型框架类(Ext JS 框架中扩展 Ext.Component 的任何类)

- 表示类、成员或指南在当前查看的版本中是新的

成员图标

- 表示类型为 config 的类成员

- 表示类型为 property 的类成员

- 表示类型为 method 的类成员

- 表示类型为 event 的类成员

- 表示类型为 theme variable 的类成员

- 表示类型为 theme mixin 的类成员

- 表示类、成员或指南在当前查看的版本中是新的

类成员快速导航菜单

在 API 文档页面上的类名正下方是一行按钮,对应于当前类拥有的成员类型。每个按钮显示按类型划分的成员计数(此计数在应用过滤器后会更新)。单击按钮将导航到该成员部分。将鼠标悬停在成员类型按钮上将显示该类型的所有成员的弹出菜单,以便快速导航。

Getter 和 Setter 方法

与类配置选项相关的 Getter 和 setter 方法将显示在方法部分以及 API 文档和成员类型菜单的配置部分中,就在它们所使用的配置下方。Getter 和 setter 方法文档将在配置行中找到,以便于参考。

历史记录栏

您的页面历史记录保存在本地存储中,并显示在顶部标题栏正下方(使用可用的实际空间)。默认情况下,显示的唯一搜索结果是与您当前查看的产品/版本匹配的页面。您可以通过单击历史记录栏右侧的 按钮并选择“全部”单选按钮来扩展显示的内容。这将显示所有产品/版本的所有最近页面历史记录栏。

在历史记录配置菜单中,您还将看到最近页面访问的列表。结果按“当前产品/版本”和“全部”单选按钮进行过滤。单击 按钮将清除历史记录栏以及本地存储中保存的历史记录。

如果在历史记录配置菜单中选择“全部”,则将启用“在历史记录栏中显示产品详细信息”复选框选项。选中后,每个历史页面的产品/版本将与历史记录栏中的页面名称一起显示。将光标悬停在历史记录栏中的页面名称上也会将产品/版本显示为工具提示。

搜索和过滤器

可以使用页面顶部的搜索字段搜索 API 文档和指南。

在 API 文档页面上,还有一个过滤器输入字段,该字段使用过滤器字符串过滤成员行。除了按字符串过滤外,您还可以按访问级别、继承和只读过滤类成员。这是通过使用页面顶部的复选框完成的。

API 类导航树底部的复选框过滤类列表,以包含或排除私有类。

单击空的搜索字段将显示您最近的 10 次搜索,以便快速导航。

API 文档类元数据

每个 API 文档页面(Javascript 原始页面除外)都有一个与该类相关的元数据菜单视图。此元数据视图将具有以下一项或多项

展开和折叠示例和类成员

可运行的示例 (Fiddle) 默认在页面上展开。您可以使用代码块左上角的箭头单独折叠和展开示例代码块。您还可以使用页面右上角的切换按钮切换所有示例的折叠状态。切换所有状态将在页面加载之间记住。

类成员默认在页面上折叠。您可以使用成员行左侧的箭头图标或使用右上角的展开/折叠全部切换按钮全局展开和折叠成员。

桌面 -vs- 移动视图

在较窄的屏幕或浏览器上查看文档将导致针对较小外形尺寸优化的视图。桌面和“移动”视图之间的主要区别在于

查看类源代码

可以通过单击 API 文档页面顶部的类名来查看类源代码。可以通过单击成员行右侧的“view source”(查看源代码)链接来查看类成员的源代码。

Ext JS 7.8.0


顶部

使用 Router 控制应用程序

在普通网站上,用户通过单击链接或填写表单在不同页面之间导航。但是,在单页应用程序中,用户的交互不会加载新页面。相反,它在单个页面中处理,组件对该交互做出反应。那么,如何仍然允许用户使用浏览器的前进和后退按钮?答案是使用 Ext JS 的 Router 消化 URI 哈希更改。

路由的用途

路由可用于通过使用浏览器历史堆栈来跟踪应用程序状态。路由还允许深度链接到应用程序,从而允许直接链接到应用程序的特定部分。这对用户非常有用,因此他们可以为您的应用程序添加书签,甚至可以将链接发送给其他人以直接访问应用程序的该部分。

路由的非用途

路由不应用于存储任何数据或会话,数据应存储在持久性数据源中,例如 cookie 或本地存储。路由仅是一种跟踪应用程序状态的方式。

什么是 Hash?

浏览器使用 URI 导航互联网,URI 由许多部分组成。让我们看一个示例 URI

https://www.example.com/apps/users#user=1234

这应该看起来相对熟悉。但是,您可能不认识 #user=1234。URI 的这一部分称为“hash”(哈希)或片段标识符。有关哈希的更多信息,请阅读此资源 http://en.wikipedia.org/wiki/Fragment_identifier。此哈希提供了一种应用程序控制浏览器历史堆栈的方式,而无需重新加载当前页面。随着哈希的变化,浏览器将整个 URI 添加到历史堆栈中,然后允许您利用浏览器的前进/后退按钮来遍历 URI,包括可能已更改的哈希。例如,如果您将哈希更新为

https://www.example.com/apps/users#user/5678

浏览器会触发一个 hashchange 事件,然后我们可以在应用程序中使用它。然后,用户可以单击后退按钮返回到 #user=1234 哈希。然后,此通知允许您对应用程序中的更改做出反应。重要的是要提到哈希不会发送到服务器。哈希通常在客户端对 URI 的解释中被消化。Ext JS Router 依赖于浏览器的哈希功能来允许应用程序状态跟踪和深度链接。

在应用程序中实现路由

Router 类是 Ext JS 的一个新增功能,旨在使 MVC 应用程序中的哈希更改解释非常简单。我们一直都有 Ext.util.History,您可以使用它来对哈希更改做出反应。但是,此 Ext.util.History 提供了更手动的过程,并且需要一个合适的 Router 类。Router 通过在视图控制器中定义路由,为 Ext JS 5+ MVC 应用程序提供简单的集成。路由是一个与哈希匹配的字符串,并允许在您的 Ext 应用程序中进行深度链接。这是一个实现 Router 的基本示例控制器

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    routes : {
        'users' : 'onUsers'
    },

    onUsers : function () {
        //...
    }
});

此路由将对 #users 哈希做出反应,并将执行作用域限定为控制器实例的 onUsers 方法。如您所见,routes 配置放置在 config 对象中,而不是在根级别。

更新 Hash

要更新哈希,控制器有一个 redirectTo 方法。

this.redirectTo('user/1234');

这将更新哈希为 "#user/1234",并且任何配置为识别哈希的路由都将执行。

redirectTo 方法还接受第二个参数以传入 options(选项)。选项是

  • force(强制) 如果为 true(真),这将强制 Router 做出反应,即使地址栏中的哈希与传递给 redirectTo 的哈希相同。
  • replace(替换) 默认情况下,哈希将被更改,并且将在浏览器的历史记录中创建一个新条目。这意味着浏览器的后退按钮可以返回到上一个哈希。如果为 true(真),则浏览器历史记录中的当前条目将被传递给 redirectTo 的哈希替换。

注意: _为了向后兼容性,options 可以是布尔值。在这种情况下,它设置的是 force 选项。

默认 Token

当应用程序启动时,如果未提供默认哈希,则可以配置为添加默认哈希。例如,如果应用程序在使用 #home 哈希时显示仪表板,您可能希望在 URI 中没有其他哈希时添加 #home 哈希。要启用默认哈希,您可以使用 /app/view/Application.js 文件中的 defaultToken 配置,该文件可以在您的应用程序中找到

Ext.define('MyApp.Application', {
    extend : 'Ext.app.Application',

    //...

    defaultToken : 'home'
});

当应用程序启动时,它将检查 URI 的当前哈希。如果定义了哈希,它将执行路由处理程序。如果未找到哈希,它将添加 #home 哈希,并且任何路由处理程序都将获得执行以适当处理它。

带有参数的 Hash

应用程序还可以在哈希中识别参数。用户 ID 是您可能想要包含在哈希中的参数示例。我们提到了在指南前面使用 #user/1234 作为哈希。在这种情况下,我们可能希望 1234 成为 id 参数。然后,您将设置您的控制器以对 #user/1234 哈希做出反应

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    routes : {
        'user/:id' : 'onUser'
    },

    onUser : function (id) {
        //...
    }
});

我们使用的路由是 'user/:id' 和冒号 :。这表示存在一个参数,您的应用程序会将该参数作为参数传递给 onUser 方法。该方法将接收传递给它的相同数量的参数,顺序与路由中指定的顺序相同,这允许轻松包含多个参数。

Hash 参数格式

应用程序可能希望对用户 ID 强制执行特定格式。在到目前为止我们探索的案例中,ID 是数字。您还可以使用路由通过使用 conditions(条件)配置来等同于对象

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    routes : {
        'user/:id' : {
            action     : 'onUser',
            conditions : {
                ':id' : '([0-9]+)'
            }
        }
    },

    onUser : function (id) {
        //...
    }
});

让我们逐步了解这个示例。首先,'onUser' 方法现在已移动到 action(操作)配置。这与我们将字符串传递给路由时的工作方式类似。然后,我们使用 conditions(条件)配置来提供一个对象。我们要控制的键是带有冒号的参数名称,我们提供一个正则表达式字符串(不是正则表达式对象)。对于 :id 条件,我们使用 ([0-9]+),这将允许 0 到 9 之间的数字,长度不限,并将记住匹配项。我们使用字符串,因为正则表达式对象用于匹配整个哈希,因此如果路由中有多个参数,我们需要将正则表达式字符串连接在一起成为单个正则表达式对象。如果您没有为参数提供条件,则它将默认为

([%a-zA-Z0-9\\-\\_\\s,]+)

路由处理

有时,应用程序可能需要阻止路由的处理。在这种情况下,我们可能想要检查管理权限,以确定是否允许当前用户查看应用程序的一部分。可以将路由配置为使用 before(之前)操作,该操作可能会停止当前路由、停止所有路由或继续执行路由。

此示例将继续执行路由

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    routes : {
        'user/:id' : {
            before  : 'onBeforeUser',
            action  : 'onUser'
        }
    },

    onBeforeUser : function (id, action) {
        Ext.Ajax.request({
            url     : '/security/user/' + id,
            success : function() {
                action.resume();
            }
        });
    },

    onUser : function (id) {
        //...
    }
});

onBeforeUser 方法中,:id 参数作为参数传递,但最后一个参数是 action(操作)。如果您在 action(操作)上执行 resume(恢复)方法,路由将继续执行,然后将调用 onUser 方法。请注意,我们可以等待 AJAX 请求完成,然后再继续执行路由。

我们可以通过告诉应用程序通过执行 stop(停止)方法来停止当前路由执行来扩展此示例

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    routes : {
        'user/:id' : {
            before  : 'onBeforeUser',
            action  : 'onUser'
        }
    },

    onBeforeUser : function (id, action) {
        Ext.Ajax.request({
            url     : '/security/user/' + id,
            success : function () {
                action.resume();
            },
            failure : function () {
                action.stop();
            }
        });
    },

    onUser : function (id) {
        //...
    }
});

before(之前)操作也支持 promise。您可以返回 promise 并 resolve(解决)或 reject(拒绝)它,而不是在 action(操作)参数上执行 resume(恢复)或 stop(停止)。在该 promise 解析后,操作将恢复或停止

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    routes : {
        'user/:id' : {
            before  : 'onBeforeUser',
            action  : 'onUser'
        }
    },

    onBeforeUser : function (id) {
        return new Ext.Promise(function (resolve, reject) {
            Ext.Ajax.request({
                url     : '/security/user/' + id,
                success : function () {
                    resolve()
                },
                failure : function () {
                    reject();
                }
            });
        });
    },

    onUser : function (id) {
        //...
    }
});

注意: 无论您使用 action(操作)参数还是返回 promise,这都是您的选择。使用任何一种方式,都需要进行解析。action(操作)参数需要执行其 resume(恢复)或 stop(停止)方法,或者 promise 需要解析或拒绝。

处理未匹配的路由

如果哈希已更改,但未找到与哈希匹配的路由,则 Router 将不执行任何操作;Router 不会尝试更改哈希,并且会保持未匹配的哈希不变。Router 将在应用程序实例上触发 unmatchedroute(未匹配路由)事件,该事件可以在 Ext.application 调用中侦听

Ext.application({
    name : 'MyApp',

    listen : {
        controller : {
            '#' : {
                unmatchedroute : 'onUnmatchedRoute'
            }
        }
    },

    onUnmatchedRoute : function (hash) {
        //...
    }
});

Router 还将触发全局事件

Ext.application({
    name : 'MyApp',

    listen : {
        global : {
            unmatchedroute : 'onUnmatchedRoute'
        }
    },

    onUnmatchedRoute : function (hash) {
        //...
    }
});

也可以直接在 Ext 命名空间上侦听全局事件

Ext.on('unmatchedroute', function (hash) {
    //...
});

在单个 Hash 中使用多个路由

由于 Ext JS 应用程序可能很复杂,因此有时我们可能需要在单个哈希中使用多个路由。Router 设置为处理此问题,因此在控制器中配置的路由无需额外设置。相反,您可以使用管道符 | 分隔哈希。示例哈希可能是

#user/1234|messages

在这种情况下,我们希望显示 id 为 1234 的用户的用户详细信息,但也显示消息。每个路由将按照哈希指示的顺序执行。然后它们彼此沙箱化。简而言之,如果您停止 user/1234 路由,则 messages 路由将继续执行。重要的是要注意,各个路由的执行顺序与路由在哈希中的顺序相同。对于上面的示例,user/1234 路由将始终在 messages 路由之前执行。

您可以通过更改 Ext.route.Router.multipleToken 属性来修改分隔符。

为了使用多个路由,redirectTo 方法也可以接受对象。这可以使您控制应更新甚至删除完整哈希的哪一部分。假设我们有 3 个不同的路由(它们也可以在不同的控制器中)

routes: {
    'bar' : 'onBar',
    'baz' : {
        action : 'onBaz',
        name   : 'bazRoute'
    },
    'foo' : 'onFoo'
}

baz 路由有一个名为 name 的新配置。原因是每个路由现在都已命名,因此我们可以更轻松地引用它。默认情况下,名称是作为 routes 对象中的键传递的 url;barfoo 是其他路由的名称。我们有 barbazRoutefoo 作为我们三个路由的名称。

初始哈希可以通过首先传递一个字符串来设置,以使哈希完全是这样

this.redirectTo('foo');

现在哈希将是 #foo。我们可以通过传递一个字符串来将另一个 token(令牌)添加到该哈希,该字符串使用 multipleToken 属性分隔两个令牌,或者通过传递一个对象

this.redirectTo({
    bar : 'bar'
});

现在哈希是 #foo|bar。让我们检查一下刚刚发生了什么。我们从 #foo 作为我们的哈希开始,并将一个对象传递到 redirectTo 并传递了 bar 键。此键应为我们正在引用的路由的名称,这就是命名概念的关键所在;对于传递的复杂 url,名称是引用它的便捷方式。如果值是 falsy(假值)并且在哈希中找到了命名路由,则将删除它。如果值是 truthy(真值)并且在哈希中找到了命名路由,则哈希的该部分将被新值替换。如果在哈希中未找到命名路由,则将其附加到哈希中。如果我们想替换 foo 路由,我们可以为其传递一个值

this.redirectTo({
    foo : 'foober'
});

现在哈希是 #foober|bar,请注意哈希中各个令牌的顺序已保留。让我们看一个更复杂的例子

this.redirectTo({
    bar      : 'barber',
    bazRoute : 'baz',
    foo      : null
});

在此示例中,我们删除了一个,更新了另一个,并添加了一个。哈希现在将是 #barber|baz。通过传递对象,您可以更好地控制哈希将是什么,而无需担心当前哈希是什么,Ext JS 将为您处理它。

自动 Hashbang 支持

如果您的应用程序需要 hashbang 而不是常规哈希,Ext JS 现在可以自动为您处理此问题。Ext.util.History 是处理从浏览器设置和获取哈希的类,Ext JS 可以在其中通过简单的属性自动将哈希设为 hashbang

Ext.util.History.hashbang = true;

现在,它将自动使用 hashbang。您的路由仍然看起来相同

routes : {
    'foo' : 'onFoo'
}

并且 redirectTo 方法的使用方式相同

this.redirectTo('foobar');

this.redirectTo({
    foo : 'foobar'
});

但是 Ext.util.History 会自动为您将哈希设为 #!foobar。Router 还可以通过使用应用程序上的新 router 配置为您设置此属性

Ext.application({
    name : 'MyApp',

    router : {
        hashbang : true
    }
});

您还可以使用 Router 上的 setter 方法

Ext.route.Router.setHashbang(true);

注意: hashbang 只是一个哈希,只是在 # 之后添加了一个 !。这意味着您不能混合和匹配哈希和 hashbang,它是二选一的。

暂停和恢复 Router

如果您需要使 Router 等待某些进程完成,以便不对哈希中的任何更改做出反应,则可以暂停 Router。暂停后,发生的任何哈希更改都将排队,并在恢复后执行。常见的用例是在应用程序启动时延迟路由执行,直到检查 store(数据存储)或用户会话为止。这是一个示例

Ext.application({
    name : 'MyApp',

    defaultToken : 'home',

    launch : function () {
        var me = this;

        Ext.route.Router.suspend();

        me
            .checkUserSession()
            .then(me.onUser.bind(me), me.onUserError.bind(me));
    },

    onUser : function (user) {
        MyApp.$user = user;

        Ext.route.Router.resume();
    },

    onUserError : function (error) {
        // handle error

        // do not execute queued hash changes
        Ext.route.Router.resume(true);

        this.redirectTo('login');
    }
});

如果您知道您不想对任何哈希更改进行排队,则 suspend(暂停)方法可以在为 false(假)时采用参数

Ext.route.Router.suspend(false);

通配符操作

如果您想在所有已配置的路由之前处理执行的路由,则可以指定通配符路由。这些通配符路由将在其他路由之前执行

routes : {
    '*'   : 'onRoute',
    'foo' : 'onFoo'
}

routes : {
    '*'   : {
        before : 'onBeforeRoute',
        action : 'onRoute'
    },
    'foo' : 'onFoo'
}

通配符路由由传递 * 作为路由的 url 来指示。它的操作将在 foo 路由之前执行。

全局事件

Ext JS 也公开了一些全局事件。这些事件在 Ext 命名空间上触发,并且可以从 Ext 命名空间或全局事件域监听。以下是这些事件:

  • beforeroutes 在任何路由执行之前触发。返回 false 允许取消执行路由。
  • beforeroute 在每个路由执行之前触发。返回 false 允许取消执行该特定路由。
  • unmatchedroute 当令牌上没有匹配的路由时触发。如果存在应用程序实例,则也会在该实例上触发。

    如前所述,有两种方法可以监听这些事件。更推荐的方式是通过控制器/视图控制器中的全局事件域进行监听。

    listen : {

      global : {
          beforeroutes : 'onBeforeRoutes'
      }
    

    },

    onBeforeRoutes : function (action, tokens) {

      return tokens.length === 1;
    

    }

或者您可以通过 Ext 命名空间进行监听

 Ext.on('unmatchedroute', function (token) {
     Ext.Msg.alert('Unmatched Route', '"' + token + '" was not matched!');
 });

Action

before action 中,您已经看到了 action 参数。这是 Ext.route.Action 的一个实例,除了恢复或停止 action 之外,还允许更多操作。这个类实际上允许代码更加动态,因为它允许您甚至在执行期间添加 beforeaction actions。

onBeforeUser : function (id, action) {
    return new Ext.Promise(function (resolve, reject) {
        action.before(function (id, action) {
            action.action(function (id) {
                //...
            });

            action.resume();
        });

        Ext.Ajax.request({
            url     : '/security/user/' + id,
            success : function () {
                resolve()
            },
            failure : function () {
                reject();
            }
        });
    });
}

在这个例子中,我们添加一个新的 before action,它将被附加到正在执行的 before actions 数组中(它将最后执行)。在该 before action 中,我们还添加一个新的 action action,它将被附加到 action actions 数组中。请注意,id 参数仍然传递给新的 actions。

如果您想了解 action 何时完全解析或拒绝(所有 beforeaction actions 都已完成),action 类有一个 then 方法。

onBeforeUser : function (id, action) {
    var me = this;

    return new Ext.Promise(function (resolve, reject) {
        action.then(Ext.bind(me.onFinish, me), Ext.bind(me.onRejection, me));

        //...
    });
}

如果在任何时候,您想停止 action 类执行其他 beforeaction actions,action 类有一个 stop 方法可以停止它的执行。

onBeforeUser : function (id, action) {
    try {
        this.foo();
    } catch (e) {
        action.stop();
    }
}

非 MVC/非 MVVM 世界中的路由

在 Ext JS 6.5.0 中创建了一个新的 mixin,现在可以在任何类中定义路由。

Ext.define('MyClass', {
    mixins : [
        'Ext.route.Mixin'
    ],

    routes : {
        'foo' : 'onFoo'
    },

    constructor : function (config) {
        this.initConfig(config);
    },

    doSomething : function () {
        this.redirectTo('foo');
    },

    onFoo : function () {
        //...
    }
});

这允许不采用 MVC 或 MVVM 架构的应用程序仍然可以使用 Router 功能。

Ext JS 7.8.0